Micron Document
NexusPi Git Node

Node / mirrors / microReticulum_Firmware / files / RNode_Firmware.ino

Displaying Raw • Download

RNode_Firmware.ino HEAD (592c826d) Text, 99.34 KB

T8b949e// Copyright (C) 2024-2026, Mark Qvist and Chad Attermann

T8b949e// This program is free software: you can redistribute it and/or modify
T8b949e// it under the terms of the GNU General Public License as published by
T8b949e// the Free Software Foundation, either version 3 of the License, or
T8b949e// (at your option) any later version.

T8b949e// This program is distributed in the hope that it will be useful,
T8b949e// but WITHOUT ANY WARRANTY; without even the implied warranty of
T8b949e// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
T8b949e// GNU General Public License for more details.

T8b949e// You should have received a copy of the GNU General Public License
T8b949e// along with this program. If not, see <https://www.gnu.org/licenses/>.

T8b949e// CBA Reticulum includes must come before local to avoid collision with local defines
Tff7b72#Tff7b72ifdef HAS_RNS
Tff7b72#Tff7b72include T8b949e<microReticulum.h>
Tff7b72#Tff7b72include T8b949e"Provisioning.h"
Tff7b72#Tff7b72if defined(LORA_TRANSPORT)
Tff7b72#Tff7b72include T8b949e"LoRaInterface.h"
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72if defined(UDP_TRANSPORT)
Tff7b72#Tff7b72include T8b949e"UDPInterface.h"
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72ifdef URTN_STATS_PAGES
Tff7b72#Tff7b72include T8b949e"Pages.h"
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72endif T8b949e// HAS_RNS
Tff7b72#Tff7b72ifdef HAS_GPIO
Tff7b72#Tff7b72include T8b949e"GPIO.h"
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72ifdef HAS_BME
Tff7b72#Tff7b72include T8b949e"BME680.h"
Tff7b72#Tff7b72endif

Tff7b72#Tff7b72include T8b949e<Arduino.h>
Tff7b72#Tff7b72include T8b949e<SPI.h>
Tff7b72#Tff7b72include T8b949e"Utilities.h"
Tff7b72#Tff7b72include T8b949e"DeviceUID.h"
Tff7b72#Tff7b72include T8b949e"Platform.h"
Tff7b72#Tff7b72include T8b949e"WebSocketConsole.h"

Tff7b72#Tff7b72if MODEM == MODEM_RUNTIME
Tff7b72#Tff7b72include T8b949e"native/LoRaFactory.h"
Tff7b72#Tff7b72include T8b949e"native/PinMap.h"
Tff7b72#Tff7b72include T8b949e"native/config.h"
Tff7b72#Tff7b72endif

T8b949e// CBA SD
Tff7b72#Tff7b72if HAS_SDCARD
Tff7b72#Tff7b72include T8b949e<SD.h>
Te6edf3SPIClass Td2a8ffSDSPITb4b4b4(Te6edf3HSPITb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif

Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32
Tff7b72#Tff7b72include T8b949e<esp_task_wdt.h>
Tff7b72#Tff7b72endif

T8b949e// WDT timeout
Tff7b72#Tff7b72define WDT_TIMEOUT 60 T8b949e// seconds

Te6edf3FIFOBuffer Te6edf3serialFIFOTb4b4b4;
Tff7b72uint8_t Te6edf3serialBufferTb4b4b4[Te6edf3CONFIG_UART_BUFFER_SIZETff7b72+T79c0ff1Tb4b4b4]Tb4b4b4;

T8b949e// Inbound byte sink used by WebSocketConsole (and any other non-polled
T8b949e// transport). Drops the byte if the FIFO is full — same behavior as the
T8b949e// existing buffer_serial() code paths for the polled sources.
Tff7b72extern Ta5d6ff"Ta5d6ffCTa5d6ff" Tff7b72void Te6edf3serial_fifo_pushTb4b4b4(Tff7b72uint8_t Tff7b72byteTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3fifo_isfullTb4b4b4(Tff7b72&Te6edf3serialFIFOTb4b4b4)Tb4b4b4) Te6edf3fifo_pushTb4b4b4(Tff7b72&Te6edf3serialFIFOTb4b4b4, Tff7b72byteTb4b4b4)Tb4b4b4;
Tb4b4b4}

Te6edf3FIFOBuffer16 Te6edf3packet_startsTb4b4b4;
Tff7b72uint16_t Te6edf3packet_starts_bufTb4b4b4[Te6edf3CONFIG_QUEUE_MAX_LENGTHTff7b72+T79c0ff1Tb4b4b4]Tb4b4b4;

Te6edf3FIFOBuffer16 Te6edf3packet_lengthsTb4b4b4;
Tff7b72uint16_t Te6edf3packet_lengths_bufTb4b4b4[Te6edf3CONFIG_QUEUE_MAX_LENGTHTff7b72+T79c0ff1Tb4b4b4]Tb4b4b4;

Tff7b72uint8_t Te6edf3packet_queueTb4b4b4[Te6edf3CONFIG_QUEUE_SIZETb4b4b4]Tb4b4b4;

Tff7b72volatile Tff7b72uint8_t Te6edf3queue_height Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72volatile Tff7b72uint16_t Te6edf3queued_bytes Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72volatile Tff7b72uint16_t Te6edf3queue_cursor Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72volatile Tff7b72uint16_t Te6edf3current_packet_start Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72volatile Tff7b72bool Te6edf3serial_buffering Tff7b72= Tff7b72falseTb4b4b4;
Tff7b72#Tff7b72if HAS_BLUETOOTH || HAS_BLE == true
Tff7b72bool Te6edf3bt_init_ran Tff7b72= Tff7b72falseTb4b4b4;
Tff7b72#Tff7b72endif

Tff7b72#Tff7b72if PLATFORM == PLATFORM_NATIVE
Tff7b72bool Te6edf3kiss_framed_logs Tff7b72= Tff7b72falseTb4b4b4;
Tff7b72#Tff7b72else
Tff7b72bool Te6edf3kiss_framed_logs Tff7b72= Tff7b72trueTb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72bool Te6edf3nomadnet_enabled Tff7b72= Tff7b72trueTb4b4b4;
Te6edf3RNSTff7b72:Tff7b72:Te6edf3Destination Te6edf3nomadnet_destination Tff7b72= Tb4b4b4{Te6edf3RNSTff7b72:Tff7b72:Te6edf3TypeTff7b72:Tff7b72:Te6edf3NONETb4b4b4}Tb4b4b4;
Tff7b72char Te6edf3nomadnet_nameTb4b4b4[T79c0ff64Tb4b4b4]Tb4b4b4;

Tff7b72#Tff7b72if HAS_CONSOLE
Tff7b72#Tff7b72include T8b949e"Console.h"
Tff7b72#Tff7b72endif

Tff7b72#Tff7b72if PLATFORM == PLATFORM_ESP32 || PLATFORM == PLATFORM_NRF52 || PLATFORM == PLATFORM_NATIVE
Tff7b72#Tff7b72define MODEM_QUEUE_SIZE 8
Tff7b72typedef Tff7b72struct Tb4b4b4{
Tffa657size_t Te6edf3lenTb4b4b4;
Tff7b72int Te6edf3rssiTb4b4b4;
Tff7b72int Te6edf3snr_rawTb4b4b4;
Tff7b72uint8_t Te6edf3dataTb4b4b4[Tb4b4b4]Tb4b4b4;
Tb4b4b4} Te6edf3modem_packet_tTb4b4b4;
Tff7b72static Te6edf3xQueueHandle Te6edf3modem_packet_queue Tff7b72= Tffa657NULLTb4b4b4;
Tff7b72#Tff7b72endif

Tff7b72char Te6edf3sbufTb4b4b4[T79c0ff128Tb4b4b4]Tb4b4b4;

Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52 || MCU_VARIANT == MCU_NATIVE
Tff7b72bool Te6edf3packet_ready Tff7b72= Tff7b72falseTb4b4b4;
Tff7b72#Tff7b72endif

Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52 || MCU_VARIANT == MCU_NATIVE
Tff7b72void Td2a8ffupdate_csma_parametersTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif

T8b949e// CBA Forward function declarations for CPP compatibility
Tff7b72void Td2a8ffserial_interrupt_initTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72void Td2a8ffvalidate_statusTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72void Td2a8ffupdate_radio_lockTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72void Td2a8fftransmitTb4b4b4(Tff7b72uint16_t Td2a8ffsizeTb4b4b4)Tb4b4b4;
Tff7b72void Td2a8ffupdate_airtimeTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72void Td2a8ffupdate_modem_statusTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72void Td2a8ffbuffer_serialTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72void Td2a8ffserial_pollTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72void Td2a8ffwork_while_waitingTb4b4b4(Tb4b4b4)Tb4b4b4;

Tff7b72#Tff7b72ifdef HAS_RNS
T8b949e/*
// CBA LoRa interface
class LoRaInterface : public RNS::InterfaceImpl {
public:
LoRaInterface(const char *name) : RNS::InterfaceImpl(name) {
_IN = true;
_OUT = true;
_HW_MTU = 508;
_bitrate = lora_bitrate;
}
LoRaInterface() : LoRaInterface("LoRaInterface") {}
virtual ~LoRaInterface() {
_name = "deleted";
}
protected:
virtual void handle_incoming(const RNS::Bytes& data) {
TRACEF("LoRaInterface.handle_incoming: (%u bytes) data: %s", data.size(), data.toHex().c_str());
TRACE("LoRaInterface.handle_incoming: sending packet to rns...");
try {
InterfaceImpl::handle_incoming(data);
}
catch (const std::bad_alloc&) {
ERROR("LoRaInterface::handle_incoming: bad_alloc - out of memory");
}
catch (std::exception& e) {
ERRORF("LoRaInterface::handle_incoming: %s", e.what());
}
}
virtual bool send_outgoing(const RNS::Bytes& data) {
// CBA NOTE header will be addded later by transmit function
TRACEF("LoRaInterface.send_outgoing: (%u bytes) data: %s", data.size(), data.toHex().c_str());
try {
TRACE("LoRaInterface.send_outgoing: adding packet to outgoing queue...");
for (size_t i = 0; i < data.size(); i++) {
if (queue_height < CONFIG_QUEUE_MAX_LENGTH && queued_bytes < CONFIG_QUEUE_SIZE) {
queued_bytes++;
packet_queue[queue_cursor++] = data.data()[i];
if (queue_cursor == CONFIG_QUEUE_SIZE) queue_cursor = 0;
}
}
if (!fifo16_isfull(&packet_starts) && queued_bytes < CONFIG_QUEUE_SIZE) {
uint16_t s = current_packet_start;
int16_t e = queue_cursor-1; if (e == -1) e = CONFIG_QUEUE_SIZE-1;
uint16_t l;

if (s != e) {
l = (s < e) ? e - s + 1 : CONFIG_QUEUE_SIZE - s + e + 1;
} else {
l = 1;
}

if (l >= MIN_L) {
queue_height++;

fifo16_push(&packet_starts, s);
fifo16_push(&packet_lengths, l);

current_packet_start = queue_cursor;
}

}
// Perform post-send housekeeping
InterfaceImpl::handle_outgoing(data);
}
catch (const std::bad_alloc&) {
ERROR("LoRaInterface::send_outgoing: bad_alloc - out of memory");
return false;
}
catch (std::exception& e) {
ERRORF("LoRaInterface::send_outgoing: %s", e.what());
return false;
}
return true;
}
};
*/

T8b949e// CBA RNS
Te6edf3RNSTff7b72:Tff7b72:Te6edf3Reticulum Td2a8ffreticulumTb4b4b4(Te6edf3RNSTff7b72:Tff7b72:Te6edf3TypeTff7b72:Tff7b72:Te6edf3NONETb4b4b4)Tb4b4b4;
Te6edf3RNSTff7b72:Tff7b72:Te6edf3Interface Td2a8fflora_interfaceTb4b4b4(Te6edf3RNSTff7b72:Tff7b72:Te6edf3TypeTff7b72:Tff7b72:Te6edf3NONETb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72if defined(UDP_TRANSPORT)
Te6edf3RNSTff7b72:Tff7b72:Te6edf3Interface Td2a8ffudp_interfaceTb4b4b4(Te6edf3RNSTff7b72:Tff7b72:Te6edf3TypeTff7b72:Tff7b72:Te6edf3NONETb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72if defined(RNS_USE_FS)
T8b949e// CBA microStore
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32
Tff7b72#Tff7b72if defined(USTORE_USE_SD)
Tff7b72#Tff7b72include T8b949e<microStore/Adapters/SDFileSystem.h>
Te6edf3microStoreTff7b72:Tff7b72:Td2a8ffFileSystem Te6edf3filesystemTb4b4b4{Te6edf3microStoreTff7b72:Tff7b72:Te6edf3AdaptersTff7b72:Tff7b72:Te6edf3SDFileSystemTb4b4b4(Te6edf3SDCARD_SCLKTb4b4b4, Te6edf3SDCARD_MISOTb4b4b4, Te6edf3SDCARD_MOSITb4b4b4, Te6edf3SDCARD_CSTb4b4b4)Tb4b4b4}Tb4b4b4;
Tff7b72#Tff7b72else
T8b949e//#include <microStore/Adapters/SPIFFSFileSystem.h>
T8b949e//microStore::FileSystem filesystem{microStore::Adapters::SPIFFSFileSystem()};
T8b949e//#include <microStore/Adapters/LittleFSFileSystem.h>
T8b949e//microStore::FileSystem filesystem{microStore::Adapters::LittleFSFileSystem()};
Tff7b72#Tff7b72include T8b949e<microStore/Adapters/PosixFileSystem.h>
Te6edf3microStoreTff7b72:Tff7b72:Td2a8ffFileSystem Te6edf3filesystemTb4b4b4{Te6edf3microStoreTff7b72:Tff7b72:Te6edf3AdaptersTff7b72:Tff7b72:Te6edf3PosixFileSystemTb4b4b4(Tb4b4b4)Tb4b4b4}Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72elif MCU_VARIANT == MCU_NRF52
Tff7b72#Tff7b72include T8b949e<microStore/Adapters/InternalFSFileSystem.h>
Tff7b72#Tff7b72include T8b949e<microStore/Adapters/FlashFSFileSystem.h>
Te6edf3microStoreTff7b72:Tff7b72:Td2a8ffFileSystem Te6edf3filesystemTb4b4b4{Te6edf3microStoreTff7b72:Tff7b72:Te6edf3AdaptersTff7b72:Tff7b72:Te6edf3InternalFSFileSystemTb4b4b4(Tb4b4b4)Tb4b4b4}Tb4b4b4;
Tff7b72#Tff7b72else
Tff7b72#Tff7b72include T8b949e<microStore/Adapters/PosixFileSystem.h>
Te6edf3microStoreTff7b72:Tff7b72:Td2a8ffFileSystem Te6edf3filesystemTb4b4b4{Te6edf3microStoreTff7b72:Tff7b72:Te6edf3AdaptersTff7b72:Tff7b72:Te6edf3PosixFileSystemTb4b4b4(Tb4b4b4)Tb4b4b4}Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72else T8b949e// RNS_USE_FS
Tff7b72#Tff7b72include T8b949e<microStore/Adapters/NoopFileSystem.h>
Te6edf3microStoreTff7b72:Tff7b72:Td2a8ffFileSystem Te6edf3filesystemTb4b4b4{Te6edf3microStoreTff7b72:Tff7b72:Te6edf3AdaptersTff7b72:Tff7b72:Te6edf3NoopFileSystemTb4b4b4(Tb4b4b4)Tb4b4b4}Tb4b4b4;
Tff7b72#Tff7b72endif T8b949e// RNS_USE_FS
Tff7b72#Tff7b72endif T8b949e// HAS_RNS
T8b949e// CBA logger callback
Tff7b72void Td2a8ffon_logTb4b4b4(Tff7b72const Tff7b72charTff7b72* Te6edf3msgTb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3LogLevel Te6edf3levelTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3kiss_framed_logsTb4b4b4) Tb4b4b4{
T8b949e// Compose "<timestamp> [<level>] <msg>" into a stack buffer to avoid
T8b949e// String heap allocation. 256 bytes covers the longest practical line.
Tff7b72char Td2a8fflineTb4b4b4[T79c0ff256Tb4b4b4]Tb4b4b4;
Tff7b72int Te6edf3n Tff7b72= Te6edf3snprintfTb4b4b4(Td2a8fflineTb4b4b4, Tff7b72sizeofTb4b4b4(Td2a8fflineTb4b4b4)Tb4b4b4, Ta5d6ff"Ta5d6ff%s [%s] %sTa5d6ff"Tb4b4b4,
Te6edf3RNSTff7b72:Tff7b72:Te6edf3getTimeStringTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3RNSTff7b72:Tff7b72:Te6edf3getLevelNameTb4b4b4(Te6edf3levelTb4b4b4)Tb4b4b4,
Te6edf3msgTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3n Tff7b72< T79c0ff0Tb4b4b4) Te6edf3n Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72if Tb4b4b4(Tb4b4b4(Tffa657size_tTb4b4b4)Te6edf3n Tff7b72>Tff7b72= Tff7b72sizeofTb4b4b4(Td2a8fflineTb4b4b4)Tb4b4b4) Te6edf3n Tff7b72= Tff7b72sizeofTb4b4b4(Td2a8fflineTb4b4b4) Tff7b72- T79c0ff1Tb4b4b4;
Te6edf3kiss_indicate_logTb4b4b4(Td2a8fflineTb4b4b4, Tb4b4b4(Tffa657size_tTb4b4b4)Te6edf3nTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72else Tb4b4b4{
T8b949e// Using individual Serial.print statements to avoid memory allocation for String
Td2a8ffSerialTb4b4b4.Td2a8ffprintTb4b4b4(Te6edf3RNSTff7b72:Tff7b72:Te6edf3getTimeStringTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Td2a8ffSerialTb4b4b4.Td2a8ffprintTb4b4b4(Ta5d6ff"Ta5d6ff [Ta5d6ff"Tb4b4b4)Tb4b4b4;
Td2a8ffSerialTb4b4b4.Td2a8ffprintTb4b4b4(Te6edf3RNSTff7b72:Tff7b72:Te6edf3getLevelNameTb4b4b4(Te6edf3levelTb4b4b4)Tb4b4b4)Tb4b4b4;
Td2a8ffSerialTb4b4b4.Td2a8ffprintTb4b4b4(Ta5d6ff"Ta5d6ff] Ta5d6ff"Tb4b4b4)Tb4b4b4;
Td2a8ffSerialTb4b4b4.Td2a8ffprintlnTb4b4b4(Te6edf3msgTb4b4b4)Tb4b4b4;
Td2a8ffSerialTb4b4b4.Td2a8ffflushTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}

Tff7b72#Tff7b72ifdef HAS_SDCARD
Td2a8ffFile Te6edf3file Tff7b72= Td2a8ffSDTb4b4b4.Td2a8ffopenTb4b4b4(Ta5d6ff"Ta5d6ff/logfile.txtTa5d6ff"Tb4b4b4, Te6edf3FILE_APPENDTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3fileTb4b4b4) Tb4b4b4{
Te6edf3fileTb4b4b4.Td2a8ffwriteTb4b4b4(Tb4b4b4(Tff7b72uint8_tTff7b72*Tb4b4b4)Te6edf3msgTb4b4b4, Te6edf3strlenTb4b4b4(Te6edf3msgTb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3fileTb4b4b4.Td2a8ffcloseTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif T8b949e// HAS_SDCARD
Tb4b4b4}

T8b949e// CBA receive packet callback
Tff7b72void Td2a8ffon_receive_packetTb4b4b4(Tff7b72const Te6edf3RNSTff7b72:Tff7b72:Te6edf3BytesTff7b72& Te6edf3rawTb4b4b4, Tff7b72const Te6edf3RNSTff7b72:Tff7b72:Te6edf3InterfaceTff7b72& Te6edf3interfaceTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72ifdef HAS_SDCARD
Te6edf3TRACETb4b4b4(Ta5d6ff"Ta5d6ffLogging receive packet to SDTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72String Td2a8ffline Tff7b72= Te6edf3RNSTff7b72:Tff7b72:Te6edf3getTimeStringTb4b4b4(Tb4b4b4) Tff7b72+ Tff7b72StringTb4b4b4(Ta5d6ff"Ta5d6ff recv: Ta5d6ff"Tb4b4b4) Tff7b72+ Tff7b72StringTb4b4b4(Te6edf3rawTb4b4b4.Te6edf3toHexTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3c_strTb4b4b4(Tb4b4b4)Tb4b4b4) Tff7b72+ Ta5d6ff"Tffea00\nTa5d6ff"Tb4b4b4;
Td2a8ffFile Te6edf3file Tff7b72= Td2a8ffSDTb4b4b4.Td2a8ffopenTb4b4b4(Ta5d6ff"Ta5d6ff./tracefile.txtTa5d6ff"Tb4b4b4, Te6edf3FILE_APPENDTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3fileTb4b4b4) Tb4b4b4{
Te6edf3fileTb4b4b4.Td2a8ffwriteTb4b4b4(Tb4b4b4(Tff7b72uint8_tTff7b72*Tb4b4b4)Td2a8fflineTb4b4b4.Te6edf3c_strTb4b4b4(Tb4b4b4)Tb4b4b4, Td2a8fflineTb4b4b4.Te6edf3lengthTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3fileTb4b4b4.Td2a8ffcloseTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3RNSTff7b72:Tff7b72:Te6edf3Packet Te6edf3packetTb4b4b4(Te6edf3rawTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3packetTb4b4b4.Te6edf3unpackTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72String Td2a8ffline Tff7b72= Te6edf3RNSTff7b72:Tff7b72:Te6edf3getTimeStringTb4b4b4(Tb4b4b4) Tff7b72+ Tff7b72StringTb4b4b4(Ta5d6ff"Ta5d6ff recv: Ta5d6ff"Tb4b4b4) Tff7b72+ Tff7b72StringTb4b4b4(Te6edf3packetTb4b4b4.Te6edf3dumpStringTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3c_strTb4b4b4(Tb4b4b4)Tb4b4b4) Tff7b72+ Ta5d6ff"Tffea00\nTa5d6ff"Tb4b4b4;
Td2a8ffFile Te6edf3file Tff7b72= Td2a8ffSDTb4b4b4.Td2a8ffopenTb4b4b4(Ta5d6ff"Ta5d6ff./tracedetails.txtTa5d6ff"Tb4b4b4, Te6edf3FILE_APPENDTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3fileTb4b4b4) Tb4b4b4{
Te6edf3fileTb4b4b4.Td2a8ffwriteTb4b4b4(Tb4b4b4(Tff7b72uint8_tTff7b72*Tb4b4b4)Td2a8fflineTb4b4b4.Te6edf3c_strTb4b4b4(Tb4b4b4)Tb4b4b4, Td2a8fflineTb4b4b4.Te6edf3lengthTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3fileTb4b4b4.Td2a8ffcloseTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72#Tff7b72endif T8b949e// HAS_SDCARD
Tff7b72#Tff7b72if PLATFORM == PLATFORM_NATIVE
Tff7b72String Td2a8ffline Tff7b72= Te6edf3RNSTff7b72:Tff7b72:Te6edf3getTimeStringTb4b4b4(Tb4b4b4) Tff7b72+ Tff7b72StringTb4b4b4(Ta5d6ff"Ta5d6ff RECV: Ta5d6ff"Tb4b4b4) Tff7b72+ Tff7b72StringTb4b4b4(Te6edf3rawTb4b4b4.Te6edf3toHexTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3c_strTb4b4b4(Tb4b4b4)Tb4b4b4) Tff7b72+ Ta5d6ff"Tffea00\nTa5d6ff"Tb4b4b4;
Te6edf3microStoreTff7b72:Tff7b72:Td2a8ffFile Te6edf3file Tff7b72= Te6edf3filesystemTb4b4b4.Td2a8ffopenTb4b4b4(Ta5d6ff"Ta5d6ff./tracefile.txtTa5d6ff"Tb4b4b4, Te6edf3microStoreTff7b72:Tff7b72:Td2a8ffFileTff7b72:Tff7b72:Te6edf3ModeAppendTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3fileTb4b4b4) Tb4b4b4{
Te6edf3fileTb4b4b4.Td2a8ffwriteTb4b4b4(Tb4b4b4(Tff7b72uint8_tTff7b72*Tb4b4b4)Td2a8fflineTb4b4b4.Te6edf3c_strTb4b4b4(Tb4b4b4)Tb4b4b4, Td2a8fflineTb4b4b4.Te6edf3lengthTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3fileTb4b4b4.Td2a8ffcloseTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3RNSTff7b72:Tff7b72:Te6edf3Packet Te6edf3packetTb4b4b4(Te6edf3rawTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3packetTb4b4b4.Te6edf3unpackTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72String Td2a8ffline Tff7b72= Te6edf3RNSTff7b72:Tff7b72:Te6edf3getTimeStringTb4b4b4(Tb4b4b4) Tff7b72+ Tff7b72StringTb4b4b4(Ta5d6ff"Ta5d6ff RECV: Ta5d6ff"Tb4b4b4) Tff7b72+ Tff7b72StringTb4b4b4(Te6edf3packetTb4b4b4.Te6edf3dumpStringTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3c_strTb4b4b4(Tb4b4b4)Tb4b4b4) Tff7b72+ Ta5d6ff"Tffea00\nTa5d6ff"Tb4b4b4;
Te6edf3microStoreTff7b72:Tff7b72:Td2a8ffFile Te6edf3file Tff7b72= Te6edf3filesystemTb4b4b4.Td2a8ffopenTb4b4b4(Ta5d6ff"Ta5d6ff./tracedetails.txtTa5d6ff"Tb4b4b4, Te6edf3microStoreTff7b72:Tff7b72:Td2a8ffFileTff7b72:Tff7b72:Te6edf3ModeAppendTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3fileTb4b4b4) Tb4b4b4{
Te6edf3fileTb4b4b4.Td2a8ffwriteTb4b4b4(Tb4b4b4(Tff7b72uint8_tTff7b72*Tb4b4b4)Td2a8fflineTb4b4b4.Te6edf3c_strTb4b4b4(Tb4b4b4)Tb4b4b4, Td2a8fflineTb4b4b4.Te6edf3lengthTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3fileTb4b4b4.Td2a8ffcloseTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4}

T8b949e// CBA transmit packet callback
Tff7b72void Td2a8ffon_transmit_packetTb4b4b4(Tff7b72const Te6edf3RNSTff7b72:Tff7b72:Te6edf3BytesTff7b72& Te6edf3rawTb4b4b4, Tff7b72const Te6edf3RNSTff7b72:Tff7b72:Te6edf3InterfaceTff7b72& Te6edf3interfaceTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72ifdef HAS_SDCARD
Te6edf3TRACETb4b4b4(Ta5d6ff"Ta5d6ffLogging transmit packet to SDTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72String Td2a8ffline Tff7b72= Te6edf3RNSTff7b72:Tff7b72:Te6edf3getTimeStringTb4b4b4(Tb4b4b4) Tff7b72+ Tff7b72StringTb4b4b4(Ta5d6ff"Ta5d6ff send: Ta5d6ff"Tb4b4b4) Tff7b72+ Tff7b72StringTb4b4b4(Te6edf3rawTb4b4b4.Te6edf3toHexTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3c_strTb4b4b4(Tb4b4b4)Tb4b4b4) Tff7b72+ Ta5d6ff"Tffea00\nTa5d6ff"Tb4b4b4;
Td2a8ffFile Te6edf3file Tff7b72= Td2a8ffSDTb4b4b4.Td2a8ffopenTb4b4b4(Ta5d6ff"Ta5d6ff/tracefile.txtTa5d6ff"Tb4b4b4, Te6edf3FILE_APPENDTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3fileTb4b4b4) Tb4b4b4{
Te6edf3fileTb4b4b4.Td2a8ffwriteTb4b4b4(Tb4b4b4(Tff7b72uint8_tTff7b72*Tb4b4b4)Td2a8fflineTb4b4b4.Te6edf3c_strTb4b4b4(Tb4b4b4)Tb4b4b4, Td2a8fflineTb4b4b4.Te6edf3lengthTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3fileTb4b4b4.Td2a8ffcloseTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3RNSTff7b72:Tff7b72:Te6edf3Packet Te6edf3packetTb4b4b4(Te6edf3rawTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3packetTb4b4b4.Te6edf3unpackTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72String Td2a8ffline Tff7b72= Te6edf3RNSTff7b72:Tff7b72:Te6edf3getTimeStringTb4b4b4(Tb4b4b4) Tff7b72+ Tff7b72StringTb4b4b4(Ta5d6ff"Ta5d6ff send: Ta5d6ff"Tb4b4b4) Tff7b72+ Tff7b72StringTb4b4b4(Te6edf3packetTb4b4b4.Te6edf3dumpStringTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3c_strTb4b4b4(Tb4b4b4)Tb4b4b4) Tff7b72+ Ta5d6ff"Tffea00\nTa5d6ff"Tb4b4b4;
Td2a8ffFile Te6edf3file Tff7b72= Td2a8ffSDTb4b4b4.Td2a8ffopenTb4b4b4(Ta5d6ff"Ta5d6ff/tracedetails.txtTa5d6ff"Tb4b4b4, Te6edf3FILE_APPENDTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3fileTb4b4b4) Tb4b4b4{
Te6edf3fileTb4b4b4.Td2a8ffwriteTb4b4b4(Tb4b4b4(Tff7b72uint8_tTff7b72*Tb4b4b4)Td2a8fflineTb4b4b4.Te6edf3c_strTb4b4b4(Tb4b4b4)Tb4b4b4, Td2a8fflineTb4b4b4.Te6edf3lengthTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3fileTb4b4b4.Td2a8ffcloseTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72#Tff7b72endif T8b949e// HAS_SDCARD
Tff7b72#Tff7b72if PLATFORM == PLATFORM_NATIVE
Tff7b72String Td2a8ffline Tff7b72= Te6edf3RNSTff7b72:Tff7b72:Te6edf3getTimeStringTb4b4b4(Tb4b4b4) Tff7b72+ Tff7b72StringTb4b4b4(Ta5d6ff"Ta5d6ff SEND: Ta5d6ff"Tb4b4b4) Tff7b72+ Tff7b72StringTb4b4b4(Te6edf3rawTb4b4b4.Te6edf3toHexTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3c_strTb4b4b4(Tb4b4b4)Tb4b4b4) Tff7b72+ Ta5d6ff"Tffea00\nTa5d6ff"Tb4b4b4;
Te6edf3microStoreTff7b72:Tff7b72:Td2a8ffFile Te6edf3file Tff7b72= Te6edf3filesystemTb4b4b4.Td2a8ffopenTb4b4b4(Ta5d6ff"Ta5d6ff./tracefile.txtTa5d6ff"Tb4b4b4, Te6edf3microStoreTff7b72:Tff7b72:Td2a8ffFileTff7b72:Tff7b72:Te6edf3ModeAppendTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3fileTb4b4b4) Tb4b4b4{
Te6edf3fileTb4b4b4.Td2a8ffwriteTb4b4b4(Tb4b4b4(Tff7b72uint8_tTff7b72*Tb4b4b4)Td2a8fflineTb4b4b4.Te6edf3c_strTb4b4b4(Tb4b4b4)Tb4b4b4, Td2a8fflineTb4b4b4.Te6edf3lengthTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3fileTb4b4b4.Td2a8ffcloseTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3RNSTff7b72:Tff7b72:Te6edf3Packet Te6edf3packetTb4b4b4(Te6edf3rawTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3packetTb4b4b4.Te6edf3unpackTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72String Td2a8ffline Tff7b72= Te6edf3RNSTff7b72:Tff7b72:Te6edf3getTimeStringTb4b4b4(Tb4b4b4) Tff7b72+ Tff7b72StringTb4b4b4(Ta5d6ff"Ta5d6ff SEND: Ta5d6ff"Tb4b4b4) Tff7b72+ Tff7b72StringTb4b4b4(Te6edf3packetTb4b4b4.Te6edf3dumpStringTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3c_strTb4b4b4(Tb4b4b4)Tb4b4b4) Tff7b72+ Ta5d6ff"Tffea00\nTa5d6ff"Tb4b4b4;
Te6edf3microStoreTff7b72:Tff7b72:Td2a8ffFile Te6edf3file Tff7b72= Te6edf3filesystemTb4b4b4.Td2a8ffopenTb4b4b4(Ta5d6ff"Ta5d6ff./tracedetails.txtTa5d6ff"Tb4b4b4, Te6edf3microStoreTff7b72:Tff7b72:Td2a8ffFileTff7b72:Tff7b72:Te6edf3ModeAppendTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3fileTb4b4b4) Tb4b4b4{
Te6edf3fileTb4b4b4.Td2a8ffwriteTb4b4b4(Tb4b4b4(Tff7b72uint8_tTff7b72*Tb4b4b4)Td2a8fflineTb4b4b4.Te6edf3c_strTb4b4b4(Tb4b4b4)Tb4b4b4, Td2a8fflineTb4b4b4.Te6edf3lengthTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3fileTb4b4b4.Td2a8ffcloseTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4}

T8b949e// For redirecting stdout to KISS framed logs
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32

Tff7b72#Tff7b72include T8b949e<esp_vfs.h>
Tff7b72#Tff7b72include T8b949e<sys/errno.h>

Tff7b72static Tffa657ssize_t Td2a8ffkiss_vfs_writeTb4b4b4(Tff7b72int Te6edf3fdTb4b4b4, Tff7b72const Tff7b72voidTff7b72* Te6edf3dataTb4b4b4, Tffa657size_t Td2a8ffsizeTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3kiss_framed_logsTb4b4b4) Tb4b4b4{
Te6edf3kiss_indicate_logTb4b4b4(Tb4b4b4(Tff7b72const Tff7b72charTff7b72*Tb4b4b4)Te6edf3dataTb4b4b4, Td2a8ffsizeTb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Td2a8ffSerialTb4b4b4.Td2a8ffwriteTb4b4b4(Tb4b4b4(Tff7b72const Tff7b72uint8_tTff7b72*Tb4b4b4)Te6edf3dataTb4b4b4, Td2a8ffsizeTb4b4b4)Tb4b4b4;
Td2a8ffSerialTb4b4b4.Td2a8ffflushTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72return Tb4b4b4(Tffa657ssize_tTb4b4b4)Td2a8ffsizeTb4b4b4;
Tb4b4b4}

Tff7b72static Tff7b72int Td2a8ffkiss_vfs_openTb4b4b4(Tff7b72const Tff7b72charTff7b72* Te6edf3pathTb4b4b4, Tff7b72int Te6edf3flagsTb4b4b4, Tff7b72int Te6edf3modeTb4b4b4) Tb4b4b4{ Tff7b72return T79c0ff0Tb4b4b4; Tb4b4b4}
Tff7b72static Tff7b72int Td2a8ffkiss_vfs_closeTb4b4b4(Tff7b72int Te6edf3fdTb4b4b4) Tb4b4b4{ Tff7b72return T79c0ff0Tb4b4b4; Tb4b4b4}
Tff7b72static Tff7b72int Td2a8ffkiss_vfs_fstatTb4b4b4(Tff7b72int Te6edf3fdTb4b4b4, Tff7b72struct T56d364statTff7b72* Te6edf3stTb4b4b4) Tb4b4b4{
Te6edf3memsetTb4b4b4(Te6edf3stTb4b4b4, T79c0ff0Tb4b4b4, Tff7b72sizeofTb4b4b4(Tff7b72*Te6edf3stTb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3stTff7b72-Tff7b72>Te6edf3st_mode Tff7b72= Te6edf3S_IFCHRTb4b4b4;
Tff7b72return T79c0ff0Tb4b4b4;
Tb4b4b4}

Tff7b72static Tff7b72void Td2a8ffinstall_kiss_stdoutTb4b4b4(Tff7b72voidTb4b4b4) Tb4b4b4{
Tff7b72static Tff7b72const Te6edf3esp_vfs_t Te6edf3kiss_vfs Tff7b72= Tb4b4b4{
Tb4b4b4.Te6edf3flags Tff7b72= Te6edf3ESP_VFS_FLAG_DEFAULTTb4b4b4,
Tb4b4b4.Td2a8ffwrite Tff7b72= Tff7b72&Te6edf3kiss_vfs_writeTb4b4b4,
Tb4b4b4.Td2a8ffopen Tff7b72= Tff7b72&Te6edf3kiss_vfs_openTb4b4b4,
Tb4b4b4.Td2a8ffclose Tff7b72= Tff7b72&Te6edf3kiss_vfs_closeTb4b4b4,
Tb4b4b4.Te6edf3fstat Tff7b72= Tff7b72&Te6edf3kiss_vfs_fstatTb4b4b4,
Tb4b4b4}Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3esp_vfs_registerTb4b4b4(Ta5d6ff"Ta5d6ff/dev/kissTa5d6ff"Tb4b4b4, Tff7b72&Te6edf3kiss_vfsTb4b4b4, Tffa657NULLTb4b4b4) Tff7b72!Tff7b72= Te6edf3ESP_OKTb4b4b4) Tff7b72returnTb4b4b4;
Tffa657FILETff7b72* Te6edf3f Tff7b72= Te6edf3fopenTb4b4b4(Ta5d6ff"Ta5d6ff/dev/kiss/0Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffwTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3fTb4b4b4) Tff7b72returnTb4b4b4;
Te6edf3setvbufTb4b4b4(Te6edf3fTb4b4b4, Tffa657NULLTb4b4b4, Te6edf3_IONBFTb4b4b4, T79c0ff0Tb4b4b4)Tb4b4b4; T8b949e// no buffering — one printf → one KISS frame
Te6edf3stdout Tff7b72= Te6edf3fTb4b4b4;
T8b949e// Optional: also redirect stderr and any ESP_LOG* output.
Te6edf3stderr Tff7b72= Te6edf3fTb4b4b4;
Te6edf3esp_log_set_vprintfTb4b4b4(Tff7b72&Te6edf3vprintfTb4b4b4)Tb4b4b4; T8b949e// ensures ESP_LOG* also goes through stdout
Tb4b4b4}

Tff7b72#Tff7b72elif MCU_VARIANT == MCU_NRF52

T8b949e// The Adafruit nRF52 core ships its own strong `_write` in main.cpp (retargets
T8b949e// newlib's printf() to Serial). Defining a second strong `_write` here would
T8b949e// produce a "multiple definition" link error, so instead we ask the linker to
T8b949e// wrap every reference to `_write` and route it at __wrap__write below.
T8b949e// Requires `-Wl,--wrap=_write` in the link flags (set in platformio.ini for
T8b949e// nRF52 envs).
Tff7b72extern Ta5d6ff"Ta5d6ffCTa5d6ff" Tff7b72int Te6edf3__wrap__writeTb4b4b4(Tff7b72int Te6edf3fileTb4b4b4, Tff7b72const Tff7b72void Tff7b72*Te6edf3ptrTb4b4b4, Tffa657size_t Te6edf3lenTb4b4b4) Tb4b4b4{
Tb4b4b4(Tff7b72voidTb4b4b4)Te6edf3fileTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3kiss_framed_logsTb4b4b4) Tb4b4b4{
Te6edf3kiss_indicate_logTb4b4b4(Tb4b4b4(Tff7b72const Tff7b72charTff7b72*Tb4b4b4)Te6edf3ptrTb4b4b4, Te6edf3lenTb4b4b4)Tb4b4b4;
Tff7b72return Tb4b4b4(Tff7b72intTb4b4b4)Te6edf3lenTb4b4b4;
Tb4b4b4}
Tff7b72int Te6edf3n Tff7b72= Td2a8ffSerialTb4b4b4.Td2a8ffwriteTb4b4b4(Tb4b4b4(Tff7b72const Tff7b72uint8_tTff7b72*Tb4b4b4)Te6edf3ptrTb4b4b4, Te6edf3lenTb4b4b4)Tb4b4b4;
Td2a8ffSerialTb4b4b4.Td2a8ffflushTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72return Te6edf3nTb4b4b4;
Tb4b4b4}

Tff7b72static Tff7b72void Te6edf3install_kiss_stdoutTb4b4b4(Tff7b72voidTb4b4b4) Tb4b4b4{Tb4b4b4}

Tff7b72#Tff7b72else

Tff7b72extern Ta5d6ff"Ta5d6ffCTa5d6ff" Tff7b72int Te6edf3_writeTb4b4b4(Tff7b72int Te6edf3fileTb4b4b4, Tff7b72char Tff7b72*Te6edf3ptrTb4b4b4, Tff7b72int Te6edf3lenTb4b4b4) Tb4b4b4{
Tffa657size_t Te6edf3wrote Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3kiss_framed_logsTb4b4b4) Tb4b4b4{
Te6edf3kiss_indicate_logTb4b4b4(Te6edf3ptrTb4b4b4, Te6edf3lenTb4b4b4)Tb4b4b4;
Te6edf3wrote Tff7b72= Te6edf3lenTb4b4b4;
Tb4b4b4}
Tff7b72else Tb4b4b4{
Te6edf3wrote Tff7b72= Td2a8ffSerialTb4b4b4.Td2a8ffwriteTb4b4b4(Te6edf3ptrTb4b4b4, Te6edf3lenTb4b4b4)Tb4b4b4;
Td2a8ffSerialTb4b4b4.Td2a8ffflushTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72return Te6edf3wroteTb4b4b4;
Tb4b4b4}

Tff7b72static Tff7b72void Te6edf3install_kiss_stdoutTb4b4b4(Tff7b72voidTb4b4b4) Tb4b4b4{Tb4b4b4}

Tff7b72#Tff7b72endif

Tff7b72#Tff7b72if defined(RNS_USE_FS)
Tff7b72void Te6edf3dump_filesystemTb4b4b4(Tff7b72const Tff7b72charTff7b72* Te6edf3basepathTb4b4b4, Tff7b72uint8_t Te6edf3level Tff7b72= T79c0ff0Tb4b4b4, Tff7b72uint8_t Te6edf3max_level Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3max_level Tff7b72> T79c0ff0 Tff7b72&Tff7b72& Te6edf3level Tff7b72> Te6edf3max_levelTb4b4b4) Tff7b72returnTb4b4b4;
Tff7b72char Te6edf3prefixTb4b4b4[T79c0ff17Tb4b4b4] Tff7b72= Ta5d6ff"Ta5d6ff"Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72uint8_t Te6edf3index Tff7b72= T79c0ff0Tb4b4b4; Te6edf3index Tff7b72< Te6edf3level Tff7b72&Tff7b72& Te6edf3index Tff7b72< T79c0ff8Tb4b4b4; Te6edf3indexTff7b72+Tff7b72+Tb4b4b4) Tb4b4b4{
Te6edf3prefixTb4b4b4[Te6edf3indexTff7b72*T79c0ff2Tb4b4b4] Tff7b72= Ta5d6ff'Ta5d6ff Ta5d6ff'Tb4b4b4;
Te6edf3prefixTb4b4b4[Te6edf3indexTff7b72*T79c0ff2Tff7b72+T79c0ff1Tb4b4b4] Tff7b72= Ta5d6ff'Ta5d6ff Ta5d6ff'Tb4b4b4;
Te6edf3prefixTb4b4b4[Te6edf3indexTff7b72*T79c0ff2Tff7b72+T79c0ff2Tb4b4b4] Tff7b72= Ta5d6ff'Ta5d6ff\0Ta5d6ff'Tb4b4b4;
Tb4b4b4}
Te6edf3filesystemTb4b4b4.Te6edf3listDirectoryTb4b4b4(Te6edf3basepathTb4b4b4, Tb4b4b4[Tff7b72&Tb4b4b4]Tb4b4b4(Tff7b72const Tff7b72charTff7b72* Te6edf3nameTb4b4b4) Tff7b72-Tff7b72> Tff7b72void Tb4b4b4{
T8b949e// Adapter callbacks receive bare basenames — join with basepath before
T8b949e// re-querying or recursing, and avoid emitting "//" when basepath is "/".
T8b949e// Skip "." and ".." directories
Tff7b72if Tb4b4b4(Te6edf3nameTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72=Tff7b72= Ta5d6ff'Ta5d6ff.Ta5d6ff'Tb4b4b4) Tff7b72returnTb4b4b4;
Tff7b72char Te6edf3fullpathTb4b4b4[T79c0ff96Tb4b4b4]Tb4b4b4;
Tff7b72const Tff7b72bool Te6edf3root Tff7b72= Tb4b4b4(Te6edf3basepathTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72=Tff7b72= Ta5d6ff'Ta5d6ff/Ta5d6ff' Tff7b72&Tff7b72& Te6edf3basepathTb4b4b4[T79c0ff1Tb4b4b4] Tff7b72=Tff7b72= Ta5d6ff'Ta5d6ff\0Ta5d6ff'Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3rootTb4b4b4) Te6edf3snprintfTb4b4b4(Te6edf3fullpathTb4b4b4, Tff7b72sizeofTb4b4b4(Te6edf3fullpathTb4b4b4)Tb4b4b4, Ta5d6ff"Ta5d6ff/%sTa5d6ff"Tb4b4b4, Te6edf3nameTb4b4b4)Tb4b4b4;
Tff7b72else Te6edf3snprintfTb4b4b4(Te6edf3fullpathTb4b4b4, Tff7b72sizeofTb4b4b4(Te6edf3fullpathTb4b4b4)Tb4b4b4, Ta5d6ff"Ta5d6ff%s/%sTa5d6ff"Tb4b4b4, Te6edf3basepathTb4b4b4, Te6edf3nameTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3filesystemTb4b4b4.Td2a8ffisDirectoryTb4b4b4(Te6edf3fullpathTb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3TRACEFTb4b4b4(Ta5d6ff"Ta5d6ff%s%s:Ta5d6ff"Tb4b4b4, Te6edf3prefixTb4b4b4, Te6edf3nameTb4b4b4)Tb4b4b4;
Te6edf3dump_filesystemTb4b4b4(Te6edf3fullpathTb4b4b4, Te6edf3level Tff7b72+ T79c0ff1Tb4b4b4, Te6edf3max_levelTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72else Tb4b4b4{
Te6edf3TRACEFTb4b4b4(Ta5d6ff"Ta5d6ff%s%sTa5d6ff"Tb4b4b4, Te6edf3prefixTb4b4b4, Te6edf3nameTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif

Tff7b72void Tffa657setupTb4b4b4(Tb4b4b4) Tb4b4b4{

T8b949e// Initialise serial communication
Te6edf3memsetTb4b4b4(Te6edf3serialBufferTb4b4b4, T79c0ff0Tb4b4b4, Tff7b72sizeofTb4b4b4(Te6edf3serialBufferTb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3fifo_initTb4b4b4(Tff7b72&Te6edf3serialFIFOTb4b4b4, Te6edf3serialBufferTb4b4b4, Te6edf3CONFIG_UART_BUFFER_SIZETb4b4b4)Tb4b4b4;

Td2a8ffSerialTb4b4b4.Td2a8ffbeginTb4b4b4(Te6edf3serial_baudrateTb4b4b4)Tb4b4b4;

T8b949e// Redirect stdout to KISS framed logs
Te6edf3install_kiss_stdoutTb4b4b4(Tb4b4b4)Tb4b4b4;

T8b949e// CBA Safely wait for serial initialization
Tff7b72while Tb4b4b4(Tff7b72!Td2a8ffSerialTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Td2a8ffmillisTb4b4b4(Tb4b4b4) Tff7b72> T79c0ff2000Tb4b4b4) Tb4b4b4{
Tff7b72breakTb4b4b4;
Tb4b4b4}
Td2a8ffdelayTb4b4b4(T79c0ff10Tb4b4b4)Tb4b4b4;
Tb4b4b4}
T8b949e// Native USB opens reset the Tracker V2. Keep its startup short enough to
T8b949e// answer rnodeconf's EEPROM request before the utility times out.
Tff7b72#Tff7b72if BOARD_MODEL != BOARD_HELTEC_TRACKER_V2
Td2a8ffdelayTb4b4b4(T79c0ff2000Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif

Tff7b72#Tff7b72ifdef HAS_RNS
Te6edf3printfTb4b4b4(Ta5d6ff"Ta5d6ffTotal SRAM: %7u bytesTffea00\nTa5d6ff"Tb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3UtilitiesTff7b72:Tff7b72:Te6edf3MemoryTff7b72:Tff7b72:Te6edf3heap_sizeTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3printfTb4b4b4(Ta5d6ff"Ta5d6ffFree SRAM: %7u bytesTffea00\nTa5d6ff"Tb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3UtilitiesTff7b72:Tff7b72:Te6edf3MemoryTff7b72:Tff7b72:Te6edf3heap_availableTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72if defined(ESP32)
Te6edf3printfTb4b4b4(Ta5d6ff"Ta5d6ffTotal PSRAM: %7u bytesTffea00\nTa5d6ff"Tb4b4b4, Te6edf3ESPTb4b4b4.Te6edf3getPsramSizeTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
T8b949e//printf("Total flash: %zu bytes\n", RNS::Utilities::OS::storage_size());

Te6edf3device_uid_initTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3INFOFTb4b4b4(Ta5d6ff"Ta5d6ffDevice UID: %sTa5d6ff"Tb4b4b4, Te6edf3device_uid_strTb4b4b4)Tb4b4b4;

Tff7b72#Tff7b72ifdef HAS_GPIO
Te6edf3GPIOTff7b72:Tff7b72:Te6edf3initTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3INFOTb4b4b4(Ta5d6ff"Ta5d6ffGPIO control initializedTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif

Tff7b72#Tff7b72ifdef HAS_BME
Te6edf3BME680Tff7b72:Tff7b72:Te6edf3initTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif

T8b949e// Configure WDT
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32
Tff7b72#Tff7b72if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
Te6edf3esp_task_wdt_config_t Te6edf3wdt_config Tff7b72= Tb4b4b4{
Tb4b4b4.Te6edf3timeout_ms Tff7b72= Te6edf3WDT_TIMEOUT Tff7b72* T79c0ff1000Tb4b4b4,
Tb4b4b4.Te6edf3idle_core_mask Tff7b72= T79c0ff0Tb4b4b4,
Tb4b4b4.Te6edf3trigger_panic Tff7b72= Tff7b72trueTb4b4b4,
Tb4b4b4}Tb4b4b4;
T8b949e// In IDF 5.x, the framework initializes TWDT before setup(); reconfigure
T8b949e// it with our timeout rather than calling init() (which would fail with
T8b949e// "TWDT already initialized"). Fall back to init() if not yet started.
Tff7b72if Tb4b4b4(Te6edf3esp_task_wdt_reconfigureTb4b4b4(Tff7b72&Te6edf3wdt_configTb4b4b4) Tff7b72=Tff7b72= Te6edf3ESP_ERR_INVALID_STATETb4b4b4) Tb4b4b4{
Te6edf3esp_task_wdt_initTb4b4b4(Tff7b72&Te6edf3wdt_configTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72else
Te6edf3esp_task_wdt_initTb4b4b4(Te6edf3WDT_TIMEOUTTb4b4b4, Tff7b72trueTb4b4b4)Tb4b4b4; T8b949e// enable panic so ESP32 restarts
Tff7b72#Tff7b72endif
Te6edf3esp_task_wdt_addTb4b4b4(Tffa657NULLTb4b4b4)Tb4b4b4; T8b949e// add current thread to WDT watch
Tff7b72#Tff7b72elif MCU_VARIANT == MCU_NRF52
Te6edf3NRF_WDTTff7b72-Tff7b72>Te6edf3CONFIG Tff7b72= T79c0ff0x01Tb4b4b4; T8b949e// Configure WDT to run when CPU is asleep
Te6edf3NRF_WDTTff7b72-Tff7b72>Te6edf3CRV Tff7b72= Te6edf3WDT_TIMEOUT Tff7b72* T79c0ff32768 Tff7b72+ T79c0ff1Tb4b4b4; T8b949e// set timeout
Te6edf3NRF_WDTTff7b72-Tff7b72>Te6edf3RREN Tff7b72= T79c0ff0x01Tb4b4b4; T8b949e// Enable the RR[0] reload register
Te6edf3NRF_WDTTff7b72-Tff7b72>Te6edf3TASKS_START Tff7b72= T79c0ff1Tb4b4b4; T8b949e// Start WDT
Tff7b72#Tff7b72endif

Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32
Te6edf3boot_seqTb4b4b4(Tb4b4b4)Tb4b4b4;
Td2a8ffEEPROMTb4b4b4.Td2a8ffbeginTb4b4b4(Te6edf3EEPROM_SIZETb4b4b4)Tb4b4b4;
Td2a8ffSerialTb4b4b4.Te6edf3setRxBufferSizeTb4b4b4(Te6edf3CONFIG_UART_BUFFER_SIZETb4b4b4)Tb4b4b4;

Tff7b72#Tff7b72if BOARD_MODEL == BOARD_TDECK
Td2a8ffpinModeTb4b4b4(Te6edf3pin_poweronTb4b4b4, Tff7b72OUTPUTTb4b4b4)Tb4b4b4;
Td2a8ffdigitalWriteTb4b4b4(Te6edf3pin_poweronTb4b4b4, Tff7b72HIGHTb4b4b4)Tb4b4b4;

Td2a8ffpinModeTb4b4b4(Te6edf3SD_CSTb4b4b4, Tff7b72OUTPUTTb4b4b4)Tb4b4b4;
Td2a8ffpinModeTb4b4b4(Te6edf3DISPLAY_CSTb4b4b4, Tff7b72OUTPUTTb4b4b4)Tb4b4b4;
Td2a8ffdigitalWriteTb4b4b4(Te6edf3SD_CSTb4b4b4, Tff7b72HIGHTb4b4b4)Tb4b4b4;
Td2a8ffdigitalWriteTb4b4b4(Te6edf3DISPLAY_CSTb4b4b4, Tff7b72HIGHTb4b4b4)Tb4b4b4;

Td2a8ffpinModeTb4b4b4(Te6edf3DISPLAY_BL_PINTb4b4b4, Tff7b72OUTPUTTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72endif

Tff7b72#Tff7b72if MCU_VARIANT == MCU_NRF52
Tff7b72#Tff7b72if BOARD_MODEL == BOARD_TECHO
Td2a8ffdelayTb4b4b4(T79c0ff200Tb4b4b4)Tb4b4b4;
Td2a8ffpinModeTb4b4b4(Te6edf3PIN_VEXT_ENTb4b4b4, Tff7b72OUTPUTTb4b4b4)Tb4b4b4;
Td2a8ffdigitalWriteTb4b4b4(Te6edf3PIN_VEXT_ENTb4b4b4, Tff7b72HIGHTb4b4b4)Tb4b4b4;
Td2a8ffpinModeTb4b4b4(Te6edf3pin_btn_usr1Tb4b4b4, Tff7b72INPUT_PULLUPTb4b4b4)Tb4b4b4;
Td2a8ffpinModeTb4b4b4(Te6edf3pin_btn_touchTb4b4b4, Tff7b72INPUT_PULLUPTb4b4b4)Tb4b4b4;
Td2a8ffpinModeTb4b4b4(Te6edf3PIN_LED_REDTb4b4b4, Tff7b72OUTPUTTb4b4b4)Tb4b4b4;
Td2a8ffpinModeTb4b4b4(Te6edf3PIN_LED_GREENTb4b4b4, Tff7b72OUTPUTTb4b4b4)Tb4b4b4;
Td2a8ffpinModeTb4b4b4(Te6edf3PIN_LED_BLUETb4b4b4, Tff7b72OUTPUTTb4b4b4)Tb4b4b4;
Td2a8ffdelayTb4b4b4(T79c0ff200Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif

Tff7b72if Tb4b4b4(Tff7b72!Te6edf3eeprom_beginTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{ Td2a8ffSerialTb4b4b4.Td2a8ffwriteTb4b4b4(Ta5d6ff"Ta5d6ffEEPROM initialisation failed.Tffea00\rTffea00\nTa5d6ff"Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72#Tff7b72endif

T8b949e// Seed the PRNG for CSMA R-value selection
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32
T8b949e// On ESP32, get the seed value from the
T8b949e// hardware RNG
Tff7b72unsigned Tff7b72long Te6edf3seed_val Tff7b72= Tb4b4b4(Tff7b72unsigned Tff7b72longTb4b4b4)Te6edf3esp_randomTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72elif MCU_VARIANT == MCU_NRF52
T8b949e// On nRF, get the seed value from the
T8b949e// hardware RNG
Tff7b72unsigned Tff7b72long Te6edf3seed_val Tff7b72= Te6edf3get_rng_seedTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72else
T8b949e// Otherwise, get a pseudo-random seed
T8b949e// value from an unconnected analog pin
T8b949e//
T8b949e// CAUTION! If you are implementing the
T8b949e// firmware on a platform that does not
T8b949e// have a hardware RNG, you MUST take
T8b949e// care to get a seed value with enough
T8b949e// entropy at each device reset!
Tff7b72unsigned Tff7b72long Te6edf3seed_val Tff7b72= Td2a8ffanalogReadTb4b4b4(T79c0ff0Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Td2a8ffrandomSeedTb4b4b4(Te6edf3seed_valTb4b4b4)Tb4b4b4;

Tff7b72#Tff7b72if HAS_NP
Te6edf3led_initTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif

Tff7b72#Tff7b72if MCU_VARIANT == MCU_NRF52 && HAS_NP == true
Te6edf3boot_seqTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif

Tff7b72#Tff7b72if BOARD_MODEL != BOARD_RAK4631 && BOARD_MODEL != BOARD_RAK3401 && BOARD_MODEL != BOARD_HELTEC_T114 && BOARD_MODEL != BOARD_TECHO && BOARD_MODEL != BOARD_T3S3 && BOARD_MODEL != BOARD_TBEAM_S_V1 && BOARD_MODEL != BOARD_HELTEC32_V4 && BOARD_MODEL != BOARD_HELTEC_TRACKER_V2
T8b949e// Some boards need to wait until the hardware UART is set up before booting
T8b949e// the full firmware. In the case of the RAK4631, RAK3401, and Heltec T114,
T8b949e// the line below will wait until a serial connection is actually established
T8b949e// with a master. Thus, it is disabled on this platform.
Tff7b72while Tb4b4b4(Tff7b72!Td2a8ffSerialTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif

Te6edf3serial_interrupt_initTb4b4b4(Tb4b4b4)Tb4b4b4;

T8b949e// Configure input and output pins
Tff7b72#Tff7b72if HAS_INPUT
Te6edf3input_initTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif

Tff7b72#Tff7b72if HAS_NP == false
T8b949e// -1 = "no LED" — skip pinMode rather than pass -1 (which Portduino's
T8b949e// pin_size_t-cast turns into 255 and asserts > NUM_GPIOS).
Tff7b72if Tb4b4b4(Te6edf3pin_led_rx Tff7b72>Tff7b72= T79c0ff0Tb4b4b4) Td2a8ffpinModeTb4b4b4(Te6edf3pin_led_rxTb4b4b4, Tff7b72OUTPUTTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3pin_led_tx Tff7b72>Tff7b72= T79c0ff0Tb4b4b4) Td2a8ffpinModeTb4b4b4(Te6edf3pin_led_txTb4b4b4, Tff7b72OUTPUTTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif

Tff7b72#Tff7b72if HAS_TCXO == true
Tff7b72if Tb4b4b4(Te6edf3pin_tcxo_enable Tff7b72!Tff7b72= T79c0ff-1Tb4b4b4) Tb4b4b4{
Td2a8ffpinModeTb4b4b4(Te6edf3pin_tcxo_enableTb4b4b4, Tff7b72OUTPUTTb4b4b4)Tb4b4b4;
Td2a8ffdigitalWriteTb4b4b4(Te6edf3pin_tcxo_enableTb4b4b4, Tff7b72HIGHTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif

T8b949e// Initialise buffers
Te6edf3memsetTb4b4b4(Te6edf3pbufTb4b4b4, T79c0ff0Tb4b4b4, Tff7b72sizeofTb4b4b4(Te6edf3pbufTb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3memsetTb4b4b4(Te6edf3cmdbufTb4b4b4, T79c0ff0Tb4b4b4, Tff7b72sizeofTb4b4b4(Te6edf3cmdbufTb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3memsetTb4b4b4(Te6edf3packet_queueTb4b4b4, T79c0ff0Tb4b4b4, Tff7b72sizeofTb4b4b4(Te6edf3packet_queueTb4b4b4)Tb4b4b4)Tb4b4b4;

Te6edf3memsetTb4b4b4(Te6edf3packet_starts_bufTb4b4b4, T79c0ff0Tb4b4b4, Tff7b72sizeofTb4b4b4(Te6edf3packet_starts_bufTb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3fifo16_initTb4b4b4(Tff7b72&Te6edf3packet_startsTb4b4b4, Te6edf3packet_starts_bufTb4b4b4, Te6edf3CONFIG_QUEUE_MAX_LENGTHTb4b4b4)Tb4b4b4;
Te6edf3memsetTb4b4b4(Te6edf3packet_lengths_bufTb4b4b4, T79c0ff0Tb4b4b4, Tff7b72sizeofTb4b4b4(Te6edf3packet_starts_bufTb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3fifo16_initTb4b4b4(Tff7b72&Te6edf3packet_lengthsTb4b4b4, Te6edf3packet_lengths_bufTb4b4b4, Te6edf3CONFIG_QUEUE_MAX_LENGTHTb4b4b4)Tb4b4b4;

Tff7b72#Tff7b72if PLATFORM == PLATFORM_ESP32 || PLATFORM == PLATFORM_NRF52 || PLATFORM == PLATFORM_NATIVE
Te6edf3modem_packet_queue Tff7b72= Te6edf3xQueueCreateTb4b4b4(Te6edf3MODEM_QUEUE_SIZETb4b4b4, Tff7b72sizeofTb4b4b4(Te6edf3modem_packet_tTff7b72*Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif

T8b949e// LoRa modem init — gated so [env:native-macos] (which removes
T8b949e// LORA_TRANSPORT via build_unflags) launches with no radio, no
T8b949e// SPI activity, and modem_installed stays false (default from Config.h).
T8b949e// Downstream `if (modem_installed)` checks handle the no-radio case.
Tff7b72#Tff7b72if defined(LORA_TRANSPORT)
T8b949e// Set chip select, reset and interrupt
T8b949e// pins for the LoRa module
Tff7b72#Tff7b72if MODEM == MODEM_RUNTIME
T8b949e// Native target: factory instantiates the runtime-selected driver and
T8b949e// performs its driver-native setPins() with the right arity using the
T8b949e// pin_* globals already populated by native_pinmap::apply().
Te6edf3LoRa Tff7b72= Te6edf3native_loraTff7b72:Tff7b72:Te6edf3create_radioTb4b4b4(Te6edf3current_modemTb4b4b4)Tb4b4b4;
T8b949e// Apply rnoded.conf SX126x overrides before preInit() / begin(). Both
T8b949e// setters are virtual no-ops on non-SX126x drivers, but we still gate
T8b949e// on current_modem so the byte conversion only runs when relevant.
Tff7b72if Tb4b4b4(Te6edf3LoRa Tff7b72!Tff7b72= Tffa657nullptr Tff7b72&Tff7b72& Te6edf3current_modem Tff7b72=Tff7b72= Te6edf3SX1262Tb4b4b4) Tb4b4b4{
Tff7b72float Te6edf3v Tff7b72= Te6edf3native_configTff7b72:Tff7b72:Te6edf3g_configTb4b4b4.Te6edf3dio3_tcxo_voltageTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3v Tff7b72> T79c0ff0.0fTb4b4b4) Tb4b4b4{
T8b949e// Snap to nearest of the 8 discrete MODE_TCXO_* bytes the SX1262
T8b949e// accepts (see sx126x.cpp MODE_TCXO_*_6X defines).
Tff7b72uint8_t Te6edf3modeTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3v Tff7b72>Tff7b72= T79c0ff3.15fTb4b4b4) Te6edf3mode Tff7b72= T79c0ff0x07Tb4b4b4; T8b949e// 3.3 V
Tff7b72else Tff7b72if Tb4b4b4(Te6edf3v Tff7b72>Tff7b72= T79c0ff2.30fTb4b4b4) Te6edf3mode Tff7b72= T79c0ff0x06Tb4b4b4; T8b949e// 2.4 / 2.7 / 3.0 V
Tff7b72else Tff7b72if Tb4b4b4(Te6edf3v Tff7b72>Tff7b72= T79c0ff2.00fTb4b4b4) Te6edf3mode Tff7b72= T79c0ff0x03Tb4b4b4; T8b949e// 2.2 V
Tff7b72else Tff7b72if Tb4b4b4(Te6edf3v Tff7b72>Tff7b72= T79c0ff1.75fTb4b4b4) Te6edf3mode Tff7b72= T79c0ff0x02Tb4b4b4; T8b949e// 1.8 V
Tff7b72else Tff7b72if Tb4b4b4(Te6edf3v Tff7b72>Tff7b72= T79c0ff1.65fTb4b4b4) Te6edf3mode Tff7b72= T79c0ff0x01Tb4b4b4; T8b949e// 1.7 V
Tff7b72else Te6edf3mode Tff7b72= T79c0ff0x00Tb4b4b4; T8b949e// 1.6 V
Te6edf3LoRaTff7b72-Tff7b72>Te6edf3setTcxoVoltageTb4b4b4(Te6edf3modeTb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3LoRaTff7b72-Tff7b72>Te6edf3setDio2AsRfSwitchTb4b4b4(Te6edf3native_configTff7b72:Tff7b72:Te6edf3g_configTb4b4b4.Te6edf3dio2_as_rf_switchTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72elif MODEM == SX1276 || MODEM == SX1278
Te6edf3LoRaTff7b72-Tff7b72>Te6edf3setPinsTb4b4b4(Te6edf3pin_csTb4b4b4, Te6edf3pin_resetTb4b4b4, Te6edf3pin_dioTb4b4b4, Te6edf3pin_busyTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72elif MODEM == SX1262
Te6edf3LoRaTff7b72-Tff7b72>Te6edf3setPinsTb4b4b4(Te6edf3pin_csTb4b4b4, Te6edf3pin_resetTb4b4b4, Te6edf3pin_dioTb4b4b4, Te6edf3pin_busyTb4b4b4, Te6edf3pin_rxenTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72elif MODEM == SX1280
Te6edf3LoRaTff7b72-Tff7b72>Te6edf3setPinsTb4b4b4(Te6edf3pin_csTb4b4b4, Te6edf3pin_resetTb4b4b4, Te6edf3pin_dioTb4b4b4, Te6edf3pin_busyTb4b4b4, Te6edf3pin_rxenTb4b4b4, Te6edf3pin_txenTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif

Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52 || MCU_VARIANT == MCU_NATIVE
Te6edf3init_channel_statsTb4b4b4(Tb4b4b4)Tb4b4b4;

Tff7b72#Tff7b72if BOARD_MODEL == BOARD_T3S3
Tff7b72#Tff7b72if MODEM == SX1280
Td2a8ffdelayTb4b4b4(T79c0ff300Tb4b4b4)Tb4b4b4;
Te6edf3LoRaTff7b72-Tff7b72>Te6edf3resetTb4b4b4(Tb4b4b4)Tb4b4b4;
Td2a8ffdelayTb4b4b4(T79c0ff100Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72endif

Tff7b72#Tff7b72if BOARD_MODEL == BOARD_XIAO_S3
T8b949e// Improve wakeup from sleep
Td2a8ffdelayTb4b4b4(T79c0ff300Tb4b4b4)Tb4b4b4;
Te6edf3LoRaTff7b72-Tff7b72>Te6edf3resetTb4b4b4(Tb4b4b4)Tb4b4b4;
Td2a8ffdelayTb4b4b4(T79c0ff100Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif

T8b949e// Check installed transceiver chip and
T8b949e// probe boot parameters.
Tff7b72#Tff7b72if MCU_VARIANT == MCU_NATIVE
T8b949e// Power up any external supplies the chip needs before preInit()
T8b949e// can read sync-word registers. Without this, a HAT with an EN
T8b949e// line (e.g. RAK13302) sees no power and the probe returns "No
T8b949e// radio module found". Leave the pins asserted after a successful
T8b949e// preInit so the chip stays powered through startRadio(); only
T8b949e// deassert on probe failure.
Te6edf3native_pinmapTff7b72:Tff7b72:Te6edf3assert_radio_enable_pinsTb4b4b4(Tb4b4b4)Tb4b4b4;
T8b949e// Pulse NRESET before the probe. On embedded targets pinMode()
T8b949e// defaults reset-line GPIOs to OUTPUT-HIGH at boot, so the chip is
T8b949e// already out of reset by the time preInit() runs; under libgpiod
T8b949e// the line stays in high-Z INPUT until reset() drives it, so the
T8b949e// chip can be stuck in reset when preInit() reads syncword regs.
T8b949e// Same pattern as the BOARD_T3S3 / BOARD_XIAO_S3 blocks above.
Td2a8ffdelayTb4b4b4(T79c0ff10Tb4b4b4)Tb4b4b4;
Te6edf3LoRaTff7b72-Tff7b72>Te6edf3resetTb4b4b4(Tb4b4b4)Tb4b4b4;
Td2a8ffdelayTb4b4b4(T79c0ff10Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72if Tb4b4b4(Te6edf3LoRaTff7b72-Tff7b72>Te6edf3preInitTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3modem_installed Tff7b72= Tff7b72trueTb4b4b4;

Tff7b72#Tff7b72if HAS_INPUT
T8b949e// Skip quick-reset console activation
Tff7b72#Tff7b72else
Tff7b72uint32_t Te6edf3lfr Tff7b72= Te6edf3LoRaTff7b72-Tff7b72>Te6edf3getFrequencyTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3lfr Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{
T8b949e// Normal boot
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3lfr Tff7b72=Tff7b72= Te6edf3M_FRQ_RTb4b4b4) Tb4b4b4{
T8b949e// Quick reboot
Tff7b72#Tff7b72if HAS_CONSOLE
Tff7b72if Tb4b4b4(Te6edf3rtc_get_reset_reasonTb4b4b4(T79c0ff0Tb4b4b4) Tff7b72=Tff7b72= Te6edf3POWERON_RESETTb4b4b4) Tb4b4b4{
Te6edf3console_active Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tb4b4b4{
T8b949e// Unknown boot
Tb4b4b4}
Te6edf3LoRaTff7b72-Tff7b72>Te6edf3setFrequencyTb4b4b4(Te6edf3M_FRQ_STb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif

Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3modem_installed Tff7b72= Tff7b72falseTb4b4b4;
Tff7b72#Tff7b72if MCU_VARIANT == MCU_NATIVE
Te6edf3native_pinmapTff7b72:Tff7b72:Te6edf3deassert_radio_enable_pinsTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tb4b4b4}
Tff7b72#Tff7b72else
T8b949e// Older variants only came with SX1276/78 chips,
T8b949e// so assume that to be the case for now.
Te6edf3modem_installed Tff7b72= Tff7b72trueTb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72endif T8b949e// defined(LORA_TRANSPORT)

Tff7b72#Tff7b72if HAS_DISPLAY
Tff7b72#Tff7b72if HAS_EEPROM
Tff7b72if Tb4b4b4(Td2a8ffEEPROMTb4b4b4.Td2a8ffreadTb4b4b4(Te6edf3eeprom_addrTb4b4b4(Te6edf3ADDR_CONF_DSETTb4b4b4)Tb4b4b4) Tff7b72!Tff7b72= Te6edf3CONF_OK_BYTETb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72elif MCU_VARIANT == MCU_NRF52
Tff7b72if Tb4b4b4(Te6edf3eeprom_readTb4b4b4(Te6edf3eeprom_addrTb4b4b4(Te6edf3ADDR_CONF_DSETTb4b4b4)Tb4b4b4) Tff7b72!Tff7b72= Te6edf3CONF_OK_BYTETb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72endif
Te6edf3eeprom_updateTb4b4b4(Te6edf3eeprom_addrTb4b4b4(Te6edf3ADDR_CONF_DSETTb4b4b4)Tb4b4b4, Te6edf3CONF_OK_BYTETb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72if BOARD_MODEL == BOARD_TECHO
Te6edf3eeprom_updateTb4b4b4(Te6edf3eeprom_addrTb4b4b4(Te6edf3ADDR_CONF_DINTTb4b4b4)Tb4b4b4, T79c0ff0x03Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72else
Te6edf3eeprom_updateTb4b4b4(Te6edf3eeprom_addrTb4b4b4(Te6edf3ADDR_CONF_DINTTb4b4b4)Tb4b4b4, T79c0ff0xFFTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tb4b4b4}
Tff7b72#Tff7b72if BOARD_MODEL == BOARD_TECHO
Te6edf3display_add_callbackTb4b4b4(Te6edf3work_while_waitingTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif

Te6edf3display_unblankTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3disp_ready Tff7b72= Te6edf3display_initTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3update_displayTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif

Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52 || MCU_VARIANT == MCU_NATIVE
Tff7b72#Tff7b72if HAS_PMU == true
Te6edf3pmu_ready Tff7b72= Te6edf3init_pmuTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif

T8b949e// Seed only erased Tracker V2 settings. Explicit user choices (including
T8b949e// disabling BLE) are represented by non-0xFF values and remain intact.
T8b949e// Radio parameters intentionally remain unset because frequency and power
T8b949e// require a region-appropriate choice during onboarding.
Tff7b72#Tff7b72if BOARD_MODEL == BOARD_HELTEC_TRACKER_V2 && HAS_EEPROM
Tff7b72if Tb4b4b4(Td2a8ffEEPROMTb4b4b4.Td2a8ffreadTb4b4b4(Te6edf3eeprom_addrTb4b4b4(Te6edf3ADDR_CONF_BTTb4b4b4)Tb4b4b4) Tff7b72=Tff7b72= T79c0ff0xFFTb4b4b4) Tb4b4b4{
Te6edf3eeprom_updateTb4b4b4(Te6edf3eeprom_addrTb4b4b4(Te6edf3ADDR_CONF_BTTb4b4b4)Tb4b4b4, Te6edf3BT_ENABLE_BYTETb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Td2a8ffEEPROMTb4b4b4.Td2a8ffreadTb4b4b4(Te6edf3eeprom_addrTb4b4b4(Te6edf3ADDR_CONF_WIFITb4b4b4)Tb4b4b4) Tff7b72=Tff7b72= T79c0ff0xFFTb4b4b4) Tb4b4b4{
Te6edf3eeprom_updateTb4b4b4(Te6edf3eeprom_addrTb4b4b4(Te6edf3ADDR_CONF_WIFITb4b4b4)Tb4b4b4, Te6edf3WR_WIFI_OFFTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif

Tff7b72#Tff7b72if HAS_BLUETOOTH || HAS_BLE == true
Te6edf3bt_initTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3bt_init_ran Tff7b72= Tff7b72trueTb4b4b4;
Tff7b72#Tff7b72endif

Tff7b72if Tb4b4b4(Te6edf3console_activeTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if HAS_CONSOLE
Te6edf3console_startTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72else
Te6edf3kiss_indicate_resetTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72#Tff7b72if HAS_WIFI
Te6edf3wifi_mode Tff7b72= Td2a8ffEEPROMTb4b4b4.Td2a8ffreadTb4b4b4(Te6edf3eeprom_addrTb4b4b4(Te6edf3ADDR_CONF_WIFITb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3wifi_mode Tff7b72=Tff7b72= Te6edf3WR_WIFI_STA Tff7b72|Tff7b72| Te6edf3wifi_mode Tff7b72=Tff7b72= Te6edf3WR_WIFI_APTb4b4b4) Tb4b4b4{ Te6edf3wifi_remote_initTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72#Tff7b72endif
Te6edf3kiss_indicate_resetTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif

Tff7b72#Tff7b72if defined(ENABLE_WEBSOCKETS) && __has_include(<WiFi.h>)
T8b949e// KISS-over-WebSocket on port 81, alongside HTTP on 80. The browser
T8b949e// page served by `server` connects back to this with `new WebSocket(
T8b949e// "ws://" + location.hostname + ":81")`. Single client at a time —
T8b949e// same model as Remote.h's KISS-over-TCP.
Te6edf3ws_consoleTff7b72:Tff7b72:Te6edf3initTb4b4b4(T79c0ff81Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif

Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52 || MCU_VARIANT == MCU_NATIVE
Tff7b72#Tff7b72if MODEM == MODEM_RUNTIME
T8b949e// Native runtime selection: SX1280 (2.4 GHz) skips interference avoidance.
Tff7b72if Tb4b4b4(Te6edf3current_modem Tff7b72=Tff7b72= Te6edf3SX1280Tb4b4b4) Tb4b4b4{
Te6edf3avoid_interference Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72#Tff7b72if HAS_EEPROM
Tff7b72uint8_t Te6edf3ia_conf Tff7b72= Td2a8ffEEPROMTb4b4b4.Td2a8ffreadTb4b4b4(Te6edf3eeprom_addrTb4b4b4(Te6edf3ADDR_CONF_DIATb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3ia_conf Tff7b72=Tff7b72= T79c0ff0x00Tb4b4b4) Tb4b4b4{ Te6edf3avoid_interference Tff7b72= Tff7b72trueTb4b4b4; Tb4b4b4}
Tff7b72else Tb4b4b4{ Te6edf3avoid_interference Tff7b72= Tff7b72falseTb4b4b4; Tb4b4b4}
Tff7b72#Tff7b72else
Te6edf3avoid_interference Tff7b72= Tff7b72falseTb4b4b4;
Tff7b72#Tff7b72endif
Tb4b4b4}
Tff7b72#Tff7b72elif MODEM == SX1280
Te6edf3avoid_interference Tff7b72= Tff7b72falseTb4b4b4;
Tff7b72#Tff7b72else
Tff7b72#Tff7b72if HAS_EEPROM
Tff7b72uint8_t Te6edf3ia_conf Tff7b72= Td2a8ffEEPROMTb4b4b4.Td2a8ffreadTb4b4b4(Te6edf3eeprom_addrTb4b4b4(Te6edf3ADDR_CONF_DIATb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3ia_conf Tff7b72=Tff7b72= T79c0ff0x00Tb4b4b4) Tb4b4b4{ Te6edf3avoid_interference Tff7b72= Tff7b72trueTb4b4b4; Tb4b4b4}
Tff7b72else Tb4b4b4{ Te6edf3avoid_interference Tff7b72= Tff7b72falseTb4b4b4; Tb4b4b4}
Tff7b72#Tff7b72elif MCU_VARIANT == MCU_NRF52
Tff7b72uint8_t Te6edf3ia_conf Tff7b72= Te6edf3eeprom_readTb4b4b4(Te6edf3eeprom_addrTb4b4b4(Te6edf3ADDR_CONF_DIATb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3ia_conf Tff7b72=Tff7b72= T79c0ff0x00Tb4b4b4) Tb4b4b4{ Te6edf3avoid_interference Tff7b72= Tff7b72trueTb4b4b4; Tb4b4b4}
Tff7b72else Tb4b4b4{ Te6edf3avoid_interference Tff7b72= Tff7b72falseTb4b4b4; Tb4b4b4}
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72endif

T8b949e// Support force-disable of interference avoidance
Tff7b72#Tff7b72ifdef DISABLE_IA
Te6edf3avoid_interference Tff7b72= Tff7b72falseTb4b4b4;
Tff7b72#Tff7b72endif

T8b949e// Validate board health, EEPROM and config
Te6edf3validate_statusTb4b4b4(Tb4b4b4)Tb4b4b4;

Tff7b72#Tff7b72if defined(LORA_TRANSPORT)
Tff7b72if Tb4b4b4(Te6edf3op_mode Tff7b72!Tff7b72= Te6edf3MODE_TNCTb4b4b4) Te6edf3LoRaTff7b72-Tff7b72>Te6edf3setFrequencyTb4b4b4(T79c0ff0Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif

T8b949e// CBA SD
Tff7b72#Tff7b72ifdef HAS_SDCARD
Td2a8ffpinModeTb4b4b4(Te6edf3SDCARD_MISOTb4b4b4, Tff7b72INPUT_PULLUPTb4b4b4)Tb4b4b4;
Te6edf3SDSPITb4b4b4.Td2a8ffbeginTb4b4b4(Te6edf3SDCARD_SCLKTb4b4b4, Te6edf3SDCARD_MISOTb4b4b4, Te6edf3SDCARD_MOSITb4b4b4, Te6edf3SDCARD_CSTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Td2a8ffSDTb4b4b4.Td2a8ffbeginTb4b4b4(Te6edf3SDCARD_CSTb4b4b4, Te6edf3SDSPITb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3printfTb4b4b4(Ta5d6ff"Ta5d6ffsetupSDCard FAILTffea00\nTa5d6ff"Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72uint32_t Te6edf3cardSize Tff7b72= Td2a8ffSDTb4b4b4.Te6edf3cardSizeTb4b4b4(Tb4b4b4) Tff7b72/ Tb4b4b4(T79c0ff1024 Tff7b72* T79c0ff1024Tb4b4b4)Tb4b4b4;
Te6edf3printfTb4b4b4(Ta5d6ff"Ta5d6ffsetupSDCard PASS . SIZE = %u GBTffea00\nTa5d6ff"Tb4b4b4, Te6edf3cardSize Tff7b72/ T79c0ff1024.0Tb4b4b4)Tb4b4b4;
Td2a8ffSDTb4b4b4.Td2a8ffremoveTb4b4b4(Ta5d6ff"Ta5d6ff/logfileTa5d6ff"Tb4b4b4)Tb4b4b4;
Td2a8ffSDTb4b4b4.Td2a8ffremoveTb4b4b4(Ta5d6ff"Ta5d6ff/logfile.txtTa5d6ff"Tb4b4b4)Tb4b4b4;
Td2a8ffSDTb4b4b4.Td2a8ffremoveTb4b4b4(Ta5d6ff"Ta5d6ff/tracefileTa5d6ff"Tb4b4b4)Tb4b4b4;
Td2a8ffSDTb4b4b4.Td2a8ffremoveTb4b4b4(Ta5d6ff"Ta5d6ff/tracedetailsTa5d6ff"Tb4b4b4)Tb4b4b4;
Td2a8ffSDTb4b4b4.Td2a8ffremoveTb4b4b4(Ta5d6ff"Ta5d6ff/tracefile.txtTa5d6ff"Tb4b4b4)Tb4b4b4;
Td2a8ffSDTb4b4b4.Td2a8ffremoveTb4b4b4(Ta5d6ff"Ta5d6ff/tracedetails.txtTa5d6ff"Tb4b4b4)Tb4b4b4;
Te6edf3printfTb4b4b4(Ta5d6ff"Ta5d6ffDIR: /Tffea00\nTa5d6ff"Tb4b4b4)Tb4b4b4;
Td2a8ffFile Te6edf3root Tff7b72= Td2a8ffSDTb4b4b4.Td2a8ffopenTb4b4b4(Ta5d6ff"Ta5d6ff/Ta5d6ff"Tb4b4b4)Tb4b4b4;
Td2a8ffFile Te6edf3file Tff7b72= Te6edf3rootTb4b4b4.Td2a8ffopenNextFileTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72whileTb4b4b4(Te6edf3fileTb4b4b4)Tb4b4b4{
Te6edf3printfTb4b4b4(Ta5d6ff"Ta5d6ff FILE: %sTffea00\nTa5d6ff"Tb4b4b4, Te6edf3fileTb4b4b4.Te6edf3nameTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3file Tff7b72= Te6edf3rootTb4b4b4.Td2a8ffopenNextFileTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Td2a8ffdelayTb4b4b4(T79c0ff3000Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif

Tff7b72#Tff7b72ifdef HAS_RNS

T8b949e// Set sane default memory limits based on hardware-specific availability
T8b949e// (note these may be adjusted dynamically based on detected hardware below)
Te6edf3RNSTff7b72:Tff7b72:Te6edf3TransportTff7b72:Tff7b72:Te6edf3path_table_maxsizeTb4b4b4(Te6edf3URTN_PATH_TABLE_MAX_RECSTb4b4b4)Tb4b4b4;
Te6edf3RNSTff7b72:Tff7b72:Te6edf3TransportTff7b72:Tff7b72:Te6edf3announce_table_maxsizeTb4b4b4(T79c0ff50Tb4b4b4)Tb4b4b4;
Te6edf3RNSTff7b72:Tff7b72:Te6edf3TransportTff7b72:Tff7b72:Te6edf3hashlist_maxsizeTb4b4b4(T79c0ff50Tb4b4b4)Tb4b4b4;
Te6edf3RNSTff7b72:Tff7b72:Te6edf3IdentityTff7b72:Tff7b72:Te6edf3known_destinations_maxsizeTb4b4b4(T79c0ff50Tb4b4b4)Tb4b4b4;
Te6edf3RNSTff7b72:Tff7b72:Te6edf3TransportTff7b72:Tff7b72:Te6edf3max_pr_tagsTb4b4b4(T79c0ff50Tb4b4b4)Tb4b4b4;
Te6edf3RNSTff7b72:Tff7b72:Te6edf3ReticulumTff7b72:Tff7b72:Te6edf3clean_intervalTb4b4b4(T79c0ff60Tff7b72*T79c0ff15Tb4b4b4)Tb4b4b4; T8b949e// 60 minutes
T8b949e//RNS::Reticulum::clean_interval(60*15); // 15 minutes
Te6edf3RNSTff7b72:Tff7b72:Te6edf3ReticulumTff7b72:Tff7b72:Te6edf3persist_intervalTb4b4b4(T79c0ff60Tff7b72*T79c0ff60Tb4b4b4)Tb4b4b4; T8b949e// 60 minutes
T8b949e//RNS::Reticulum::persist_interval(60*10); // 10 minutes
T8b949e//RNS::Reticulum::persist_interval(60); // 1 minute

T8b949e// Configure callbacks
Te6edf3RNSTff7b72:Tff7b72:Te6edf3set_log_callbackTb4b4b4(Tff7b72&Te6edf3on_logTb4b4b4)Tb4b4b4;
Te6edf3RNSTff7b72:Tff7b72:Te6edf3TransportTff7b72:Tff7b72:Te6edf3set_receive_packet_callbackTb4b4b4(Te6edf3on_receive_packetTb4b4b4)Tb4b4b4;
Te6edf3RNSTff7b72:Tff7b72:Te6edf3TransportTff7b72:Tff7b72:Te6edf3set_transmit_packet_callbackTb4b4b4(Te6edf3on_transmit_packetTb4b4b4)Tb4b4b4;

Tff7b72try Tb4b4b4{
T8b949e// CBA Init filesystem
Te6edf3HEADTb4b4b4(Ta5d6ff"Ta5d6ffInitializing filesystem...Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3LOG_TRACETb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72if BOARD_MODEL == BOARD_RAK4631 || BOARD_MODEL == BOARD_RAK3401
Tff7b72bool Te6edf3init_success Tff7b72= Tff7b72falseTb4b4b4;
T8b949e// Attempt to initialize RAK15001 flash
Tb4b4b4{
Te6edf3TRACETb4b4b4(Ta5d6ff"Ta5d6ffLooking for RAK15001 flash...Ta5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72static Tff7b72const Te6edf3SPIFlash_Device_t Te6edf3device Tff7b72= Te6edf3RAK15001Tb4b4b4;
T8b949e// CBA NOTE: RAK base boards generally *share* the same chip select (CS/SS) across all module slots.
T8b949e// SS below is expected to be configured as the "external" SPI bus chip select.
Te6edf3filesystem Tff7b72= Te6edf3microStoreTff7b72:Tff7b72:Te6edf3AdaptersTff7b72:Tff7b72:Te6edf3FlashFSFileSystemTb4b4b4(Tff7b72&Te6edf3deviceTb4b4b4, Te6edf3SSTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3filesystemTb4b4b4.Te6edf3initTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3TRACETb4b4b4(Ta5d6ff"Ta5d6ffInitialized RAK15001 flashTa5d6ff"Tb4b4b4)Tb4b4b4;
Te6edf3init_success Tff7b72= Tff7b72trueTb4b4b4;
T8b949e// Raise path store limits to account for larger external flash size
Te6edf3RNSTff7b72:Tff7b72:Te6edf3TransportTff7b72:Tff7b72:Te6edf3path_table_maxsizeTb4b4b4(T79c0ff500Tb4b4b4)Tb4b4b4;
Te6edf3RNSTff7b72:Tff7b72:Te6edf3TransportTff7b72:Tff7b72:Te6edf3path_store_segment_sizeTb4b4b4(T79c0ff24576Tb4b4b4)Tb4b4b4;
Te6edf3RNSTff7b72:Tff7b72:Te6edf3TransportTff7b72:Tff7b72:Te6edf3path_store_segment_countTb4b4b4(T79c0ff8Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
T8b949e// Attempt to initialize W25Q128 flash
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3init_successTb4b4b4) Tb4b4b4{
Te6edf3TRACETb4b4b4(Ta5d6ff"Ta5d6ffLooking for W25Q128 flash...Ta5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72static Tff7b72const Te6edf3SPIFlash_Device_t Te6edf3device Tff7b72= Te6edf3W25Q128Tb4b4b4;
T8b949e// CBA NOTE: RAK base boards generally *share* the same chip select (CS/SS) across all module slots.
T8b949e// This particular module is expected to be on an *alternate* chip select gpio WB_IO1.
Te6edf3filesystem Tff7b72= Te6edf3microStoreTff7b72:Tff7b72:Te6edf3AdaptersTff7b72:Tff7b72:Te6edf3FlashFSFileSystemTb4b4b4(Tff7b72&Te6edf3deviceTb4b4b4, Te6edf3WB_IO1Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3filesystemTb4b4b4.Te6edf3initTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3TRACETb4b4b4(Ta5d6ff"Ta5d6ffInitialized W25Q128 flashTa5d6ff"Tb4b4b4)Tb4b4b4;
Te6edf3init_success Tff7b72= Tff7b72trueTb4b4b4;
T8b949e// Raise path store limits to account for larger external flash size
Te6edf3RNSTff7b72:Tff7b72:Te6edf3TransportTff7b72:Tff7b72:Te6edf3path_table_maxsizeTb4b4b4(T79c0ff500Tb4b4b4)Tb4b4b4;
Te6edf3RNSTff7b72:Tff7b72:Te6edf3TransportTff7b72:Tff7b72:Te6edf3path_store_segment_sizeTb4b4b4(T79c0ff24576Tb4b4b4)Tb4b4b4;
Te6edf3RNSTff7b72:Tff7b72:Te6edf3TransportTff7b72:Tff7b72:Te6edf3path_store_segment_countTb4b4b4(T79c0ff8Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
T8b949e// If no other initialize attempts succeeded then fallback to internal flash
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3init_successTb4b4b4) Tb4b4b4{
Te6edf3TRACETb4b4b4(Ta5d6ff"Ta5d6ffUsing internal flash...Ta5d6ff"Tb4b4b4)Tb4b4b4;
Te6edf3filesystem Tff7b72= Te6edf3microStoreTff7b72:Tff7b72:Te6edf3AdaptersTff7b72:Tff7b72:Te6edf3InternalFSFileSystemTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3filesystemTb4b4b4.Te6edf3initTb4b4b4(Tb4b4b4)Tb4b4b4) Te6edf3WARNINGTb4b4b4(Ta5d6ff"Ta5d6ffFailed to initialize filesystem!Ta5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72else Te6edf3TRACETb4b4b4(Ta5d6ff"Ta5d6ffInitialized internal flashTa5d6ff"Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72else
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3filesystemTb4b4b4.Te6edf3initTb4b4b4(Tb4b4b4)Tb4b4b4) Te6edf3WARNINGTb4b4b4(Ta5d6ff"Ta5d6ffFailed to initialize filesystem!Ta5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif

T8b949e// Remove legacy files
Te6edf3filesystemTb4b4b4.Td2a8ffremoveTb4b4b4(Ta5d6ff"Ta5d6ff./destination_tableTa5d6ff"Tb4b4b4)Tb4b4b4;
Te6edf3filesystemTb4b4b4.Td2a8ffremoveTb4b4b4(Ta5d6ff"Ta5d6ff./path_store_index.datTa5d6ff"Tb4b4b4)Tb4b4b4;
Te6edf3filesystemTb4b4b4.Td2a8ffremoveTb4b4b4(Ta5d6ff"Ta5d6ff./path_store_0.datTa5d6ff"Tb4b4b4)Tb4b4b4;
Te6edf3filesystemTb4b4b4.Td2a8ffremoveTb4b4b4(Ta5d6ff"Ta5d6ff./path_store_1.datTa5d6ff"Tb4b4b4)Tb4b4b4;
Te6edf3filesystemTb4b4b4.Td2a8ffremoveTb4b4b4(Ta5d6ff"Ta5d6ff./path_store_2.datTa5d6ff"Tb4b4b4)Tb4b4b4;
Te6edf3filesystemTb4b4b4.Td2a8ffremoveTb4b4b4(Ta5d6ff"Ta5d6ff./path_store_3.datTa5d6ff"Tb4b4b4)Tb4b4b4;
Te6edf3filesystemTb4b4b4.Td2a8ffremoveTb4b4b4(Ta5d6ff"Ta5d6ff./path_store_4.datTa5d6ff"Tb4b4b4)Tb4b4b4;
Te6edf3filesystemTb4b4b4.Td2a8ffremoveTb4b4b4(Ta5d6ff"Ta5d6ff./path_store_5.datTa5d6ff"Tb4b4b4)Tb4b4b4;
Te6edf3filesystemTb4b4b4.Td2a8ffremoveTb4b4b4(Ta5d6ff"Ta5d6ff./path_store_6.datTa5d6ff"Tb4b4b4)Tb4b4b4;
Te6edf3filesystemTb4b4b4.Td2a8ffremoveTb4b4b4(Ta5d6ff"Ta5d6ff./path_store_7.datTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3filesystemTb4b4b4.Td2a8ffisDirectoryTb4b4b4(Ta5d6ff"Ta5d6ff./cacheTa5d6ff"Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3filesystemTb4b4b4.Te6edf3listDirectoryTb4b4b4(Ta5d6ff"Ta5d6ff./cacheTa5d6ff"Tb4b4b4, Tb4b4b4[Tff7b72&Tb4b4b4]Tb4b4b4(Tff7b72const Tff7b72charTff7b72* Te6edf3nameTb4b4b4) Tff7b72-Tff7b72> Tff7b72void Tb4b4b4{
Tff7b72char Te6edf3rmpathTb4b4b4[T79c0ff64Tb4b4b4]Tb4b4b4;
Te6edf3snprintfTb4b4b4(Te6edf3rmpathTb4b4b4, Tff7b72sizeofTb4b4b4(Te6edf3rmpathTb4b4b4)Tb4b4b4, Ta5d6ff"Ta5d6ff./cache/%sTa5d6ff"Tb4b4b4, Te6edf3nameTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3filesystemTb4b4b4.Td2a8ffisDirectoryTb4b4b4(Te6edf3rmpathTb4b4b4)Tb4b4b4) Te6edf3filesystemTb4b4b4.Td2a8ffrmdirTb4b4b4(Te6edf3rmpathTb4b4b4)Tb4b4b4;
Tff7b72else Te6edf3filesystemTb4b4b4.Td2a8ffremoveTb4b4b4(Te6edf3rmpathTb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3filesystemTb4b4b4.Td2a8ffrmdirTb4b4b4(Ta5d6ff"Ta5d6ff./cacheTa5d6ff"Tb4b4b4)Tb4b4b4;
Tb4b4b4}

Tff7b72#Tff7b72if PLATFORM != PLATFORM_NATIVE
T8b949e// If filesystem is essentially full then clear all path store files
Tff7b72if Tb4b4b4(Te6edf3filesystemTb4b4b4.Te6edf3storageAvailableTb4b4b4(Tb4b4b4) Tff7b72< T79c0ff1024Tb4b4b4) Tb4b4b4{
Te6edf3WARNINGTb4b4b4(Ta5d6ff"Ta5d6ffFileSystem is full, clearing space...Ta5d6ff"Tb4b4b4)Tb4b4b4;
T8b949e// CBA Delete the path store index file to force a rebuild
Te6edf3filesystemTb4b4b4.Td2a8ffremoveTb4b4b4(Ta5d6ff"Ta5d6ff/path_store/index.datTa5d6ff"Tb4b4b4)Tb4b4b4;
T8b949e// CBA Remove all path store data files
Te6edf3filesystemTb4b4b4.Td2a8ffremoveTb4b4b4(Ta5d6ff"Ta5d6ff/path_store/seg0.datTa5d6ff"Tb4b4b4)Tb4b4b4;
Te6edf3filesystemTb4b4b4.Td2a8ffremoveTb4b4b4(Ta5d6ff"Ta5d6ff/path_store/seg1.datTa5d6ff"Tb4b4b4)Tb4b4b4;
Te6edf3filesystemTb4b4b4.Td2a8ffremoveTb4b4b4(Ta5d6ff"Ta5d6ff/path_store/seg2.datTa5d6ff"Tb4b4b4)Tb4b4b4;
Te6edf3filesystemTb4b4b4.Td2a8ffremoveTb4b4b4(Ta5d6ff"Ta5d6ff/path_store/seg3.datTa5d6ff"Tb4b4b4)Tb4b4b4;
Te6edf3filesystemTb4b4b4.Td2a8ffremoveTb4b4b4(Ta5d6ff"Ta5d6ff/path_store/seg4.datTa5d6ff"Tb4b4b4)Tb4b4b4;
Te6edf3filesystemTb4b4b4.Td2a8ffremoveTb4b4b4(Ta5d6ff"Ta5d6ff/path_store/seg5.datTa5d6ff"Tb4b4b4)Tb4b4b4;
Te6edf3filesystemTb4b4b4.Td2a8ffremoveTb4b4b4(Ta5d6ff"Ta5d6ff/path_store/seg6.datTa5d6ff"Tb4b4b4)Tb4b4b4;
Te6edf3filesystemTb4b4b4.Td2a8ffremoveTb4b4b4(Ta5d6ff"Ta5d6ff/path_store/seg7.datTa5d6ff"Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif

Te6edf3TRACETb4b4b4(Ta5d6ff"Ta5d6ffRegistering filesystem...Ta5d6ff"Tb4b4b4)Tb4b4b4;
Te6edf3RNSTff7b72:Tff7b72:Te6edf3UtilitiesTff7b72:Tff7b72:Te6edf3OSTff7b72:Tff7b72:Te6edf3register_filesystemTb4b4b4(Te6edf3filesystemTb4b4b4)Tb4b4b4;

Tff7b72#Tff7b72if defined(RNS_USE_FS)
Tff7b72#if 0
T8b949e filesystem.format();
Tff7b72#endif
Tff7b72#Tff7b72if 1
Te6edf3TRACETb4b4b4(Ta5d6ff"Ta5d6ffListing filesystem...Ta5d6ff"Tb4b4b4)Tb4b4b4;
Te6edf3dump_filesystemTb4b4b4(Ta5d6ff"Ta5d6ff./Ta5d6ff"Tb4b4b4, T79c0ff1Tb4b4b4, T79c0ff2Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72endif T8b949e// RNS_USE_FS

T8b949e// CBA Start RNS
T8b949e//if (hw_ready) {
Tff7b72if Tb4b4b4(Tff7b72trueTb4b4b4) Tb4b4b4{

Tff7b72#Tff7b72if defined(LORA_TRANSPORT)
Te6edf3lora_interface Tff7b72= Tff7b72new Te6edf3LoRaInterfaceTb4b4b4(Tb4b4b4)Tb4b4b4;
T8b949e// Provisioning default
Te6edf3lora_interfaceTb4b4b4.Te6edf3modeTb4b4b4(Te6edf3RNSTff7b72:Tff7b72:Te6edf3TypeTff7b72:Tff7b72:Te6edf3InterfaceTff7b72:Tff7b72:Te6edf3MODE_GATEWAYTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72if HAS_WIFI && defined(UDP_TRANSPORT)
Tff7b72if Tb4b4b4(Te6edf3wifi_mode Tff7b72!Tff7b72= Te6edf3WR_WIFI_OFFTb4b4b4) Tb4b4b4{
Te6edf3udp_interface Tff7b72= Tff7b72new Te6edf3UDPInterfaceTb4b4b4(Tb4b4b4)Tb4b4b4;
T8b949e// Provisioning default
Te6edf3udp_interfaceTb4b4b4.Te6edf3modeTb4b4b4(Te6edf3RNSTff7b72:Tff7b72:Te6edf3TypeTff7b72:Tff7b72:Te6edf3InterfaceTff7b72:Tff7b72:Te6edf3MODE_GATEWAYTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif

T8b949e// Provisioning default
Te6edf3reticulumTb4b4b4.Te6edf3transport_enabledTb4b4b4(Tff7b72trueTb4b4b4)Tb4b4b4;
T8b949e// Provisioning default
Te6edf3reticulumTb4b4b4.Te6edf3probe_destination_enabledTb4b4b4(Tff7b72trueTb4b4b4)Tb4b4b4;
T8b949e// Provisioning default
Te6edf3reticulumTb4b4b4.Te6edf3remote_management_enabledTb4b4b4(Tff7b72trueTb4b4b4)Tb4b4b4;

Tff7b72#Tff7b72ifdef URTN_STATS_PAGES
T8b949e// Provisioning default
Te6edf3snprintfTb4b4b4(Te6edf3nomadnet_nameTb4b4b4, Tff7b72sizeofTb4b4b4(Te6edf3nomadnet_nameTb4b4b4)Tb4b4b4, Ta5d6ff"Ta5d6ffmicroReticulum Node [%s]Ta5d6ff"Tb4b4b4, Te6edf3device_uid_strTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif

Tff7b72#Tff7b72ifdef HAS_PROVISIONING
T8b949e// Bring the Provisioning subsystem up. Loads persisted MsgPack files
T8b949e// (including the radio + general namespaces registered here) and fires
T8b949e// FF_LIVE_APPLY setters. FF_REBOOT_REQUIRED setters only fire if the
T8b949e// disk value differs from the declared default — so on a fresh device
T8b949e// the lora_* globals stay at their Config.h defaults until either
T8b949e// eeprom_conf_load() runs or a Provisioning SetState arrives.
T8b949e// CBA NOTE: All app-default-values must be set *before* calling init_provisioning so that they take effect for fresh installs
Te6edf3HEADTb4b4b4(Ta5d6ff"Ta5d6ffInitializing Provisioning subsystem...Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3LOG_TRACETb4b4b4)Tb4b4b4;
Te6edf3init_provisioningTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72autoTff7b72& Te6edf3prov Tff7b72= Te6edf3RNSTff7b72:Tff7b72:Te6edf3ProvisioningTff7b72:Tff7b72:Te6edf3ProvisionerTff7b72:Tff7b72:Te6edf3instanceTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif

T8b949e//reticulum.clear_caches();

Te6edf3HEADTb4b4b4(Ta5d6ff"Ta5d6ffStarting RNS...Tffea00\rTffea00\nTa5d6ff"Tb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3LOG_VERBOSETb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72if defined(RNS_MEM_LOG)
Te6edf3RNSTff7b72:Tff7b72:Te6edf3loglevelTb4b4b4(Te6edf3RNSTff7b72:Tff7b72:Te6edf3LOG_MEMTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72else
Te6edf3RNSTff7b72:Tff7b72:Te6edf3loglevelTb4b4b4(Te6edf3RNSTff7b72:Tff7b72:Te6edf3LOG_TRACETb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif

Tff7b72#Tff7b72if defined(LORA_TRANSPORT)
Te6edf3HEADTb4b4b4(Ta5d6ff"Ta5d6ffRegistering LoRA Interface...Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3LOG_TRACETb4b4b4)Tb4b4b4;
Te6edf3RNSTff7b72:Tff7b72:Te6edf3TransportTff7b72:Tff7b72:Te6edf3register_interfaceTb4b4b4(Te6edf3lora_interfaceTb4b4b4)Tb4b4b4;
Te6edf3TRACEFTb4b4b4(Ta5d6ff"Ta5d6ffLoRaInterface hash: %sTa5d6ff"Tb4b4b4, Te6edf3lora_interfaceTb4b4b4.Te6edf3get_hashTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3toHexTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3c_strTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72if HAS_WIFI && defined(UDP_TRANSPORT)
Tff7b72if Tb4b4b4(Te6edf3wifi_mode Tff7b72!Tff7b72= Te6edf3WR_WIFI_OFFTb4b4b4) Tb4b4b4{
Te6edf3HEADTb4b4b4(Ta5d6ff"Ta5d6ffRegistering UDP Interface...Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3LOG_TRACETb4b4b4)Tb4b4b4;
Te6edf3RNSTff7b72:Tff7b72:Te6edf3TransportTff7b72:Tff7b72:Te6edf3register_interfaceTb4b4b4(Te6edf3udp_interfaceTb4b4b4)Tb4b4b4;
Te6edf3TRACEFTb4b4b4(Ta5d6ff"Ta5d6ffUDPInterface hash: %sTa5d6ff"Tb4b4b4, Te6edf3udp_interfaceTb4b4b4.Te6edf3get_hashTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3toHexTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3c_strTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif

Te6edf3HEADTb4b4b4(Ta5d6ff"Ta5d6ffCreating Reticulum instance...Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3LOG_TRACETb4b4b4)Tb4b4b4;
Te6edf3reticulum Tff7b72= Te6edf3RNSTff7b72:Tff7b72:Te6edf3ReticulumTb4b4b4(Tb4b4b4)Tb4b4b4;
T8b949e// CBA NOTE: `transport_enabled` needs to always be overridden to false when op_mode is not MODE_TNC
Te6edf3printfTb4b4b4(Ta5d6ff"Ta5d6ff[init] hw_ready: %uTffea00\nTa5d6ff"Tb4b4b4, Te6edf3hw_readyTb4b4b4)Tb4b4b4;
Te6edf3printfTb4b4b4(Ta5d6ff"Ta5d6ff[init] op_mode: %UTffea00\nTa5d6ff"Tb4b4b4, Te6edf3op_modeTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3op_mode Tff7b72!Tff7b72= Te6edf3MODE_TNCTb4b4b4) Tb4b4b4{
Te6edf3INFOTb4b4b4(Ta5d6ff"Ta5d6ffNot in TNC mode, transport will be disabledTa5d6ff"Tb4b4b4)Tb4b4b4;
Te6edf3reticulumTb4b4b4.Te6edf3transport_enabledTb4b4b4(Tff7b72falseTb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3reticulumTb4b4b4.Te6edf3startTb4b4b4(Tb4b4b4)Tb4b4b4;

T8b949e// Set loop callback only after the Reticulum instance is started
T8b949e// (to avoid looping without a completely initialized instance)
Te6edf3RNSTff7b72:Tff7b72:Te6edf3UtilitiesTff7b72:Tff7b72:Te6edf3OSTff7b72:Tff7b72:Te6edf3set_loop_callbackTb4b4b4(Tff7b72&Tffa657loopTb4b4b4)Tb4b4b4;

T8b949e// CBA load/create local destination for admin node
Tff7b72#if 0
T8b949e RNS::Identity identity = {RNS::Type::NONE};
T8b949e std::string local_identity_path = RNS::Reticulum::_storagepath + "/local_identity";
T8b949e if (RNS::Utilities::OS::file_exists(local_identity_path.c_str())) {
T8b949e identity = RNS::Identity::from_file(local_identity_path.c_str());
T8b949e }
T8b949e if (!identity) {
T8b949e RNS::verbose("No valid local identity in storage, creating...");
T8b949e identity = RNS::Identity();
T8b949e identity.to_file(local_identity_path.c_str());
T8b949e }
T8b949e else {
T8b949e RNS::verbose("Loaded local identity from storage");
T8b949e }
T8b949e RNS::Destination destination(identity, RNS::Type::Destination::IN, RNS::Type::Destination::SINGLE, "rnstransport", "local");
Tff7b72#endif
T8b949e//RNS::Destination destination(RNS::Transport::identity(), RNS::Type::Destination::IN, RNS::Type::Destination::SINGLE, "rnstransport", "local");

Tff7b72#Tff7b72ifdef URTN_STATS_PAGES
Tff7b72if Tb4b4b4(Te6edf3nomadnet_enabledTb4b4b4) Tb4b4b4{
T8b949e// Create an IN/SINGLE destination on the NomadNet aspect, so
T8b949e// clients (like a Python NomadNet browser) can find
T8b949e// us by aspect/announce and open a Link.
Te6edf3nomadnet_destination Tff7b72= Te6edf3RNSTff7b72:Tff7b72:Te6edf3DestinationTb4b4b4(
Te6edf3RNSTff7b72:Tff7b72:Te6edf3TransportTff7b72:Tff7b72:Te6edf3identityTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3RNSTff7b72:Tff7b72:Te6edf3TypeTff7b72:Tff7b72:Te6edf3DestinationTff7b72:Tff7b72:Te6edf3INTb4b4b4,
Te6edf3RNSTff7b72:Tff7b72:Te6edf3TypeTff7b72:Tff7b72:Te6edf3DestinationTff7b72:Tff7b72:Te6edf3SINGLETb4b4b4,
Ta5d6ff"Ta5d6ffnomadnetworkTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffnodeTa5d6ff"
Tb4b4b4)Tb4b4b4;

T8b949e// Register the page handler. ALLOW_ALL because page browsing is open
T8b949e// to anyone who can reach the node, just like a Python NomadNet
T8b949e// node's default policy.
T8b949e//nomadnet_destination.register_request_handler("/page/index.mu", serve_page, RNS::Type::Destination::ALLOW_LIST, RNS::Transport::remote_management_allowed());
Te6edf3nomadnet_destinationTb4b4b4.Te6edf3register_request_handlerTb4b4b4(Ta5d6ff"Ta5d6ff/page/index.muTa5d6ff"Tb4b4b4, Te6edf3serve_pageTb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3TypeTff7b72:Tff7b72:Te6edf3DestinationTff7b72:Tff7b72:Te6edf3ALLOW_ALLTb4b4b4)Tb4b4b4;
Te6edf3nomadnet_destinationTb4b4b4.Te6edf3register_request_handlerTb4b4b4(Ta5d6ff"Ta5d6ff/page/stack.muTa5d6ff"Tb4b4b4, Te6edf3serve_pageTb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3TypeTff7b72:Tff7b72:Te6edf3DestinationTff7b72:Tff7b72:Te6edf3ALLOW_LISTTb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3TransportTff7b72:Tff7b72:Te6edf3remote_management_allowedTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3nomadnet_destinationTb4b4b4.Te6edf3register_request_handlerTb4b4b4(Ta5d6ff"Ta5d6ff/page/device.muTa5d6ff"Tb4b4b4, Te6edf3serve_pageTb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3TypeTff7b72:Tff7b72:Te6edf3DestinationTff7b72:Tff7b72:Te6edf3ALLOW_LISTTb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3TransportTff7b72:Tff7b72:Te6edf3remote_management_allowedTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72ifdef HAS_BME
Tff7b72if Tb4b4b4(Te6edf3BME680Tff7b72:Tff7b72:Te6edf3bme_installedTb4b4b4) Tb4b4b4{
Te6edf3nomadnet_destinationTb4b4b4.Te6edf3register_request_handlerTb4b4b4(Ta5d6ff"Ta5d6ff/page/telemetry.muTa5d6ff"Tb4b4b4, Te6edf3serve_pageTb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3TypeTff7b72:Tff7b72:Te6edf3DestinationTff7b72:Tff7b72:Te6edf3ALLOW_ALLTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif

T8b949e// Announce once at startup so a client that's already listening can
T8b949e// discover us immediately. The node name is sent as the announce
T8b949e// app_data (plain UTF-8 bytes), matching nomadnet/Node.py:217-222 —
T8b949e// this is what other NomadNet clients show in their site listing.
Tb4b4b4{
Te6edf3NOTICEFTb4b4b4(Ta5d6ff"Ta5d6ffAnnouncing NomadNet site Tffea00\"Ta5d6ff%sTffea00\"Ta5d6ff at destination <%s>Ta5d6ff"Tb4b4b4, Te6edf3nomadnet_nameTb4b4b4, Te6edf3nomadnet_destinationTb4b4b4.Te6edf3hashTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3toHexTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3c_strTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3nomadnet_destinationTb4b4b4.Te6edf3announceTb4b4b4(Te6edf3nomadnet_nameTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72#Tff7b72endif T8b949e// URTN_STATS_PAGES

Te6edf3HEADTb4b4b4(Ta5d6ff"Ta5d6ffRNS is READY!Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3LOG_TRACETb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3op_mode Tff7b72=Tff7b72= Te6edf3MODE_TNCTb4b4b4) Tb4b4b4{
Te6edf3HEADTb4b4b4(Ta5d6ff"Ta5d6ffRNS transport mode is ENABLEDTa5d6ff"Tb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3LOG_TRACETb4b4b4)Tb4b4b4;
Te6edf3TRACEFTb4b4b4(Ta5d6ff"Ta5d6ffFrequency: %d HzTa5d6ff"Tb4b4b4, Te6edf3lora_freqTb4b4b4)Tb4b4b4;
Te6edf3TRACEFTb4b4b4(Ta5d6ff"Ta5d6ffBandwidth: %d HzTa5d6ff"Tb4b4b4, Te6edf3lora_bwTb4b4b4)Tb4b4b4;
Te6edf3TRACEFTb4b4b4(Ta5d6ff"Ta5d6ffSpreading Factor: %dTa5d6ff"Tb4b4b4, Te6edf3lora_sfTb4b4b4)Tb4b4b4;
Te6edf3TRACEFTb4b4b4(Ta5d6ff"Ta5d6ffCoding Rate: %dTa5d6ff"Tb4b4b4, Te6edf3lora_crTb4b4b4)Tb4b4b4;
Te6edf3TRACEFTb4b4b4(Ta5d6ff"Ta5d6ffTX Power: %d dBmTa5d6ff"Tb4b4b4, Te6edf3lora_txpTb4b4b4)Tb4b4b4;
Te6edf3HEADTb4b4b4(Ta5d6ff"Ta5d6ffRNS Transport is READY!Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3LOG_TRACETb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72else Tb4b4b4{
Te6edf3HEADTb4b4b4(Ta5d6ff"Ta5d6ffRNS transport mode is DISABLEDTa5d6ff"Tb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3LOG_INFOTb4b4b4)Tb4b4b4;
Te6edf3HEADTb4b4b4(Ta5d6ff"Ta5d6ffConfigure TNC mode with radio configuration to enable RNS transportTa5d6ff"Tb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3LOG_INFOTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72else Tb4b4b4{
Te6edf3HEADTb4b4b4(Ta5d6ff"Ta5d6ffRNS is inoperable because hardware is not ready!Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3LOG_ERRORTb4b4b4)Tb4b4b4;
Te6edf3HEADTb4b4b4(Ta5d6ff"Ta5d6ffCheck firmware signature and eeprom provisioningTa5d6ff"Tb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3LOG_ERRORTb4b4b4)Tb4b4b4;
T8b949e// CBA Clear cached files just in case cached files are responsible for failure
T8b949e//reticulum.clear_caches();
Tb4b4b4}
Tb4b4b4}
Tff7b72catch Tb4b4b4(Tff7b72const Te6edf3stdTff7b72:Tff7b72:Te6edf3bad_allocTff7b72&Tb4b4b4) Tb4b4b4{
Te6edf3ERRORTb4b4b4(Ta5d6ff"Ta5d6ffRNS startup failed: bad_alloc - out of memoryTa5d6ff"Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72catch Tb4b4b4(Te6edf3stdTff7b72:Tff7b72:Te6edf3exceptionTff7b72& Te6edf3eTb4b4b4) Tb4b4b4{
Te6edf3ERRORFTb4b4b4(Ta5d6ff"Ta5d6ffRNS startup failed: %sTa5d6ff"Tb4b4b4, Te6edf3eTb4b4b4.Te6edf3whatTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif T8b949e// HAS_RNS
Tb4b4b4}

Tff7b72void Te6edf3lora_receiveTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3implicitTb4b4b4) Tb4b4b4{
Te6edf3LoRaTff7b72-Tff7b72>Te6edf3receiveTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3LoRaTff7b72-Tff7b72>Te6edf3receiveTb4b4b4(Te6edf3implicit_lTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}

Tff7b72inline Tff7b72void Te6edf3kiss_write_packetTb4b4b4(Tb4b4b4) Tb4b4b4{

Tff7b72#Tff7b72if defined(HAS_RNS) && defined(LORA_TRANSPORT)
Tff7b72if Tb4b4b4(Te6edf3host_write_len Tff7b72> T79c0ff0Tb4b4b4) Tb4b4b4{
Te6edf3printfTb4b4b4(Ta5d6ff"Ta5d6ff[radio] Received %d byte packetTa5d6ff"Tb4b4b4, Te6edf3host_write_lenTb4b4b4)Tb4b4b4;
T8b949e// CBA send packet received over LoRa to RNS in addition to connected client
Te6edf3RNSTff7b72:Tff7b72:Te6edf3Bytes Td2a8ffdataTb4b4b4(Te6edf3pbufTb4b4b4, Te6edf3host_write_lenTb4b4b4)Tb4b4b4;
Te6edf3lora_interfaceTb4b4b4.Te6edf3r_stat_rssiTb4b4b4(Te6edf3last_rssiTb4b4b4)Tb4b4b4;
Te6edf3lora_interfaceTb4b4b4.Te6edf3r_stat_snrTb4b4b4(Tb4b4b4(Tb4b4b4(Tff7b72int8_tTb4b4b4)Te6edf3last_snr_rawTb4b4b4) Tff7b72/ T79c0ff4.0fTb4b4b4)Tb4b4b4;
Te6edf3lora_interfaceTb4b4b4.Te6edf3r_stat_qTb4b4b4(Te6edf3get_qualityTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3lora_interfaceTb4b4b4.Te6edf3handle_incomingTb4b4b4(Te6edf3dataTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif

Te6edf3serial_writeTb4b4b4(Te6edf3FENDTb4b4b4)Tb4b4b4;
Te6edf3serial_writeTb4b4b4(Te6edf3CMD_DATATb4b4b4)Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72uint16_t Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3i Tff7b72< Te6edf3host_write_lenTb4b4b4; Te6edf3iTff7b72+Tff7b72+Tb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if MCU_VARIANT == MCU_NRF52
Te6edf3portENTER_CRITICALTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72uint8_t Tff7b72byte Tff7b72= Te6edf3pbufTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4;
Te6edf3portEXIT_CRITICALTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72else
Tff7b72uint8_t Tff7b72byte Tff7b72= Te6edf3pbufTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4;
Tff7b72#Tff7b72endif

Tff7b72if Tb4b4b4(Tff7b72byte Tff7b72=Tff7b72= Te6edf3FENDTb4b4b4) Tb4b4b4{ Te6edf3serial_writeTb4b4b4(Te6edf3FESCTb4b4b4)Tb4b4b4; Tff7b72byte Tff7b72= Te6edf3TFENDTb4b4b4; Tb4b4b4}
Tff7b72if Tb4b4b4(Tff7b72byte Tff7b72=Tff7b72= Te6edf3FESCTb4b4b4) Tb4b4b4{ Te6edf3serial_writeTb4b4b4(Te6edf3FESCTb4b4b4)Tb4b4b4; Tff7b72byte Tff7b72= Te6edf3TFESCTb4b4b4; Tb4b4b4}
Te6edf3serial_writeTb4b4b4(Tff7b72byteTb4b4b4)Tb4b4b4;
Tb4b4b4}

Te6edf3serial_writeTb4b4b4(Te6edf3FENDTb4b4b4)Tb4b4b4;
Te6edf3host_write_len Tff7b72= T79c0ff0Tb4b4b4;

Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52 || MCU_VARIANT == MCU_NATIVE
Te6edf3packet_ready Tff7b72= Tff7b72falseTb4b4b4;
Tff7b72#Tff7b72endif

Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32
Tff7b72#Tff7b72if HAS_BLE
Te6edf3bt_flushTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72endif
Tb4b4b4}

Tff7b72inline Tff7b72void Te6edf3getPacketDataTb4b4b4(Tff7b72uint16_t Te6edf3lenTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if MCU_VARIANT != MCU_NRF52
Tff7b72while Tb4b4b4(Te6edf3lenTff7b72-Tff7b72- Tff7b72&Tff7b72& Te6edf3read_len Tff7b72< Te6edf3MTUTb4b4b4) Tb4b4b4{
Te6edf3pbufTb4b4b4[Te6edf3read_lenTff7b72+Tff7b72+Tb4b4b4] Tff7b72= Te6edf3LoRaTff7b72-Tff7b72>Td2a8ffreadTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72else
Te6edf3BaseType_t Te6edf3int_mask Tff7b72= Te6edf3taskENTER_CRITICAL_FROM_ISRTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72while Tb4b4b4(Te6edf3lenTff7b72-Tff7b72- Tff7b72&Tff7b72& Te6edf3read_len Tff7b72< Te6edf3MTUTb4b4b4) Tb4b4b4{
Te6edf3pbufTb4b4b4[Te6edf3read_lenTff7b72+Tff7b72+Tb4b4b4] Tff7b72= Te6edf3LoRaTff7b72-Tff7b72>Td2a8ffreadTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3taskEXIT_CRITICAL_FROM_ISRTb4b4b4(Te6edf3int_maskTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tb4b4b4}

Tff7b72void Te6edf3ISR_VECT Te6edf3receive_callbackTb4b4b4(Tff7b72int Te6edf3packet_sizeTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52
Te6edf3BaseType_t Te6edf3int_maskTb4b4b4;
Tff7b72#Tff7b72endif

Tff7b72bool Td2a8ffready Tff7b72= Tff7b72falseTb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3promiscTb4b4b4) Tb4b4b4{ T8b949e// Not in promiscuous mode
T8b949e// The standard operating mode allows large
T8b949e// packets with a payload up to 500 bytes,
T8b949e// by combining two raw LoRa packets.
T8b949e// We read the 1-byte header and extract
T8b949e// packet sequence number and split flags
Tff7b72uint8_t Te6edf3header Tff7b72= Te6edf3LoRaTff7b72-Tff7b72>Td2a8ffreadTb4b4b4(Tb4b4b4)Tb4b4b4; Te6edf3packet_sizeTff7b72-Tff7b72-Tb4b4b4;
Tff7b72uint8_t Te6edf3sequence Tff7b72= Te6edf3packetSequenceTb4b4b4(Te6edf3headerTb4b4b4)Tb4b4b4;

Tff7b72if Tb4b4b4(Te6edf3isSplitPacketTb4b4b4(Te6edf3headerTb4b4b4) Tff7b72&Tff7b72& Te6edf3seq Tff7b72=Tff7b72= Te6edf3SEQ_UNSETTb4b4b4) Tb4b4b4{
T8b949e// This is the first part of a split
T8b949e// packet, so we set the seq variable
T8b949e// and add the data to the buffer
Tff7b72#Tff7b72if MCU_VARIANT == MCU_NRF52
Te6edf3int_mask Tff7b72= Te6edf3taskENTER_CRITICAL_FROM_ISRTb4b4b4(Tb4b4b4)Tb4b4b4; Te6edf3read_len Tff7b72= T79c0ff0Tb4b4b4; Te6edf3taskEXIT_CRITICAL_FROM_ISRTb4b4b4(Te6edf3int_maskTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72else
Te6edf3read_len Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72#Tff7b72endif
Te6edf3seq Tff7b72= Te6edf3sequenceTb4b4b4;

Tff7b72#Tff7b72if MCU_VARIANT != MCU_ESP32 && MCU_VARIANT != MCU_NRF52 && MCU_VARIANT != MCU_NATIVE
Te6edf3last_rssi Tff7b72= Te6edf3LoRaTff7b72-Tff7b72>Te6edf3packetRssiTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3last_snr_raw Tff7b72= Te6edf3LoRaTff7b72-Tff7b72>Te6edf3packetSnrRawTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif

Te6edf3getPacketDataTb4b4b4(Te6edf3packet_sizeTb4b4b4)Tb4b4b4;

Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3isSplitPacketTb4b4b4(Te6edf3headerTb4b4b4) Tff7b72&Tff7b72& Te6edf3seq Tff7b72=Tff7b72= Te6edf3sequenceTb4b4b4) Tb4b4b4{
T8b949e// This is the second part of a split
T8b949e// packet, so we add it to the buffer
T8b949e// and set the ready flag.
Tff7b72#Tff7b72if MCU_VARIANT != MCU_ESP32 && MCU_VARIANT != MCU_NRF52 && MCU_VARIANT != MCU_NATIVE
Te6edf3last_rssi Tff7b72= Tb4b4b4(Te6edf3last_rssiTff7b72+Te6edf3LoRaTff7b72-Tff7b72>Te6edf3packetRssiTb4b4b4(Tb4b4b4)Tb4b4b4)Tff7b72/T79c0ff2Tb4b4b4;
Te6edf3last_snr_raw Tff7b72= Tb4b4b4(Te6edf3last_snr_rawTff7b72+Te6edf3LoRaTff7b72-Tff7b72>Te6edf3packetSnrRawTb4b4b4(Tb4b4b4)Tb4b4b4)Tff7b72/T79c0ff2Tb4b4b4;
Tff7b72#Tff7b72endif

Te6edf3getPacketDataTb4b4b4(Te6edf3packet_sizeTb4b4b4)Tb4b4b4;
Te6edf3seq Tff7b72= Te6edf3SEQ_UNSETTb4b4b4;
Td2a8ffready Tff7b72= Tff7b72trueTb4b4b4;

Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3isSplitPacketTb4b4b4(Te6edf3headerTb4b4b4) Tff7b72&Tff7b72& Te6edf3seq Tff7b72!Tff7b72= Te6edf3sequenceTb4b4b4) Tb4b4b4{
T8b949e// This split packet does not carry the
T8b949e// same sequence id, so we must assume
T8b949e// that we are seeing the first part of
T8b949e// a new split packet.
Tff7b72#Tff7b72if MCU_VARIANT == MCU_NRF52
Te6edf3int_mask Tff7b72= Te6edf3taskENTER_CRITICAL_FROM_ISRTb4b4b4(Tb4b4b4)Tb4b4b4; Te6edf3read_len Tff7b72= T79c0ff0Tb4b4b4; Te6edf3taskEXIT_CRITICAL_FROM_ISRTb4b4b4(Te6edf3int_maskTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72else
Te6edf3read_len Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72#Tff7b72endif
Te6edf3seq Tff7b72= Te6edf3sequenceTb4b4b4;

Tff7b72#Tff7b72if MCU_VARIANT != MCU_ESP32 && MCU_VARIANT != MCU_NRF52 && MCU_VARIANT != MCU_NATIVE
Te6edf3last_rssi Tff7b72= Te6edf3LoRaTff7b72-Tff7b72>Te6edf3packetRssiTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3last_snr_raw Tff7b72= Te6edf3LoRaTff7b72-Tff7b72>Te6edf3packetSnrRawTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif

Te6edf3getPacketDataTb4b4b4(Te6edf3packet_sizeTb4b4b4)Tb4b4b4;

Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Tff7b72!Te6edf3isSplitPacketTb4b4b4(Te6edf3headerTb4b4b4)Tb4b4b4) Tb4b4b4{
T8b949e// This is not a split packet, so we
T8b949e// just read it and set the ready
T8b949e// flag to true.

Tff7b72if Tb4b4b4(Te6edf3seq Tff7b72!Tff7b72= Te6edf3SEQ_UNSETTb4b4b4) Tb4b4b4{
T8b949e// If we already had part of a split
T8b949e// packet in the buffer, we clear it.
Tff7b72#Tff7b72if MCU_VARIANT == MCU_NRF52
Te6edf3int_mask Tff7b72= Te6edf3taskENTER_CRITICAL_FROM_ISRTb4b4b4(Tb4b4b4)Tb4b4b4; Te6edf3read_len Tff7b72= T79c0ff0Tb4b4b4; Te6edf3taskEXIT_CRITICAL_FROM_ISRTb4b4b4(Te6edf3int_maskTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72else
Te6edf3read_len Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72#Tff7b72endif
Te6edf3seq Tff7b72= Te6edf3SEQ_UNSETTb4b4b4;
Tb4b4b4}

Tff7b72#Tff7b72if MCU_VARIANT != MCU_ESP32 && MCU_VARIANT != MCU_NRF52 && MCU_VARIANT != MCU_NATIVE
Te6edf3last_rssi Tff7b72= Te6edf3LoRaTff7b72-Tff7b72>Te6edf3packetRssiTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3last_snr_raw Tff7b72= Te6edf3LoRaTff7b72-Tff7b72>Te6edf3packetSnrRawTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif

Te6edf3getPacketDataTb4b4b4(Te6edf3packet_sizeTb4b4b4)Tb4b4b4;
Td2a8ffready Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{ T8b949e// In promiscuous mode
T8b949e// In promiscuous mode, raw packets are
T8b949e// output directly to the host
Te6edf3read_len Tff7b72= T79c0ff0Tb4b4b4;

Tff7b72#Tff7b72if MCU_VARIANT != MCU_ESP32 && MCU_VARIANT != MCU_NRF52 && MCU_VARIANT != MCU_NATIVE
Te6edf3last_rssi Tff7b72= Te6edf3LoRaTff7b72-Tff7b72>Te6edf3packetRssiTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3last_snr_raw Tff7b72= Te6edf3LoRaTff7b72-Tff7b72>Te6edf3packetSnrRawTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3getPacketDataTb4b4b4(Te6edf3packet_sizeTb4b4b4)Tb4b4b4;

T8b949e// We first signal the RSSI of the
T8b949e// recieved packet to the host.
Te6edf3kiss_indicate_stat_rssiTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3kiss_indicate_stat_snrTb4b4b4(Tb4b4b4)Tb4b4b4;

T8b949e// And then write the entire packet
Te6edf3kiss_write_packetTb4b4b4(Tb4b4b4)Tb4b4b4;

Tff7b72#Tff7b72else
Te6edf3getPacketDataTb4b4b4(Te6edf3packet_sizeTb4b4b4)Tb4b4b4;
Te6edf3packet_ready Tff7b72= Tff7b72trueTb4b4b4;
Tff7b72#Tff7b72endif
Tb4b4b4}

Tff7b72if Tb4b4b4(Td2a8ffreadyTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if MCU_VARIANT != MCU_ESP32 && MCU_VARIANT != MCU_NRF52 && MCU_VARIANT != MCU_NATIVE
T8b949e// We first signal the RSSI of the
T8b949e// recieved packet to the host.
Te6edf3kiss_indicate_stat_rssiTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3kiss_indicate_stat_snrTb4b4b4(Tb4b4b4)Tb4b4b4;

T8b949e// And then write the entire packet
Te6edf3host_write_len Tff7b72= Te6edf3read_lenTb4b4b4;
Te6edf3kiss_write_packetTb4b4b4(Tb4b4b4)Tb4b4b4; Te6edf3read_len Tff7b72= T79c0ff0Tb4b4b4;

Tff7b72#Tff7b72else
T8b949e// Allocate packet struct, but abort if there
T8b949e// is not enough memory available.
Te6edf3modem_packet_t Tff7b72*Te6edf3modem_packet Tff7b72= Tb4b4b4(Te6edf3modem_packet_tTff7b72*Tb4b4b4)Te6edf3mallocTb4b4b4(Tff7b72sizeofTb4b4b4(Te6edf3modem_packet_tTb4b4b4) Tff7b72+ Te6edf3read_lenTb4b4b4)Tb4b4b4;
Tff7b72ifTb4b4b4(Tff7b72!Te6edf3modem_packetTb4b4b4) Tb4b4b4{ Te6edf3memory_low Tff7b72= Tff7b72trueTb4b4b4; Tff7b72returnTb4b4b4; Tb4b4b4}

T8b949e// Get packet RSSI and SNR
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NATIVE
Te6edf3modem_packetTff7b72-Tff7b72>Te6edf3snr_raw Tff7b72= Te6edf3LoRaTff7b72-Tff7b72>Te6edf3packetSnrRawTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3modem_packetTff7b72-Tff7b72>Te6edf3rssi Tff7b72= Te6edf3LoRaTff7b72-Tff7b72>Te6edf3packetRssiTb4b4b4(Te6edf3modem_packetTff7b72-Tff7b72>Te6edf3snr_rawTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif

T8b949e// Send packet to event queue, but free the
T8b949e// allocated memory again if the queue is
T8b949e// unable to receive the packet.
Te6edf3modem_packetTff7b72-Tff7b72>Te6edf3len Tff7b72= Te6edf3read_lenTb4b4b4;
Te6edf3memcpyTb4b4b4(Te6edf3modem_packetTff7b72-Tff7b72>Te6edf3dataTb4b4b4, Te6edf3pbufTb4b4b4, Te6edf3read_lenTb4b4b4)Tb4b4b4; Te6edf3read_len Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3modem_packet_queue Tff7b72|Tff7b72| Te6edf3xQueueSendFromISRTb4b4b4(Te6edf3modem_packet_queueTb4b4b4, Tff7b72&Te6edf3modem_packetTb4b4b4, Tffa657NULLTb4b4b4) Tff7b72!Tff7b72= Te6edf3pdPASSTb4b4b4) Tb4b4b4{
Te6edf3freeTb4b4b4(Te6edf3modem_packetTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4}
Tb4b4b4}

Tff7b72bool Te6edf3startRadioTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3update_radio_lockTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3radio_online Tff7b72&Tff7b72& Tff7b72!Te6edf3console_activeTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3radio_locked Tff7b72&Tff7b72& Te6edf3hw_readyTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if MCU_VARIANT == MCU_NATIVE
T8b949e// Drive any configured radio_enable_pins to their active level
T8b949e// before the modem comes up so external rails (LDOs, TCXO supply,
T8b949e// PA bias) are stable before the SX126x probes them.
Te6edf3native_pinmapTff7b72:Tff7b72:Te6edf3assert_radio_enable_pinsTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3LoRaTff7b72-Tff7b72>Td2a8ffbeginTb4b4b4(Te6edf3lora_freqTb4b4b4)Tb4b4b4) Tb4b4b4{
T8b949e// The radio could not be started.
T8b949e// Indicate this failure over both the
T8b949e// serial port and with the onboard LEDs
Tff7b72#Tff7b72if MCU_VARIANT == MCU_NATIVE
Te6edf3native_pinmapTff7b72:Tff7b72:Te6edf3deassert_radio_enable_pinsTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Te6edf3radio_error Tff7b72= Tff7b72trueTb4b4b4;
Te6edf3kiss_indicate_errorTb4b4b4(Te6edf3ERROR_INITRADIOTb4b4b4)Tb4b4b4;
Te6edf3led_indicate_errorTb4b4b4(T79c0ff0Tb4b4b4)Tb4b4b4;
Tff7b72return Tff7b72falseTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3radio_online Tff7b72= Tff7b72trueTb4b4b4;

Te6edf3init_channel_statsTb4b4b4(Tb4b4b4)Tb4b4b4;

Te6edf3setTXPowerTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3setBandwidthTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3setSpreadingFactorTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3setCodingRateTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3getFrequencyTb4b4b4(Tb4b4b4)Tb4b4b4;

Te6edf3LoRaTff7b72-Tff7b72>Te6edf3enableCrcTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3LoRaTff7b72-Tff7b72>Td2a8ffonReceiveTb4b4b4(Te6edf3receive_callbackTb4b4b4)Tb4b4b4;
Te6edf3lora_receiveTb4b4b4(Tb4b4b4)Tb4b4b4;

T8b949e// Flash an info pattern to indicate
T8b949e// that the radio is now on
Te6edf3kiss_indicate_radiostateTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3led_indicate_infoTb4b4b4(T79c0ff3Tb4b4b4)Tb4b4b4;
Tff7b72return Tff7b72trueTb4b4b4;
Tb4b4b4}

Tb4b4b4} Tff7b72else Tb4b4b4{
T8b949e// Flash a warning pattern to indicate
T8b949e// that the radio was locked, and thus
T8b949e// not started
Te6edf3radio_online Tff7b72= Tff7b72falseTb4b4b4;
Te6edf3kiss_indicate_radiostateTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3led_indicate_warningTb4b4b4(T79c0ff3Tb4b4b4)Tb4b4b4;
Tff7b72return Tff7b72falseTb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{
T8b949e// If radio is already on, we silently
T8b949e// ignore the request.
Te6edf3kiss_indicate_radiostateTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72return Tff7b72trueTb4b4b4;
Tb4b4b4}
Tb4b4b4}

Tff7b72void Te6edf3stopRadioTb4b4b4(Tb4b4b4) Tb4b4b4{
T8b949e// Idempotent: LoRa->end() calls SPI.end() which nulls Portduino's
T8b949e// spiChip on native. The main loop's `else { stopRadio(); }` branch
T8b949e// fires every iteration while radio_online is false, so we must not
T8b949e// re-end an already-stopped radio — otherwise the next SPI access
T8b949e// (e.g. lora_receive() at the tail of flush_queue) asserts on a null
T8b949e// spiChip.
Tff7b72#Tff7b72if defined(LORA_TRANSPORT)
Tff7b72if Tb4b4b4(Te6edf3radio_onlineTb4b4b4) Te6edf3LoRaTff7b72-Tff7b72>Td2a8ffendTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Te6edf3radio_online Tff7b72= Tff7b72falseTb4b4b4;
Tff7b72#Tff7b72if MCU_VARIANT == MCU_NATIVE
T8b949e// De-assert after LoRa->end() so SPI cleanup completes while supply
T8b949e// rails are still up — avoids transients on power-down.
Te6edf3native_pinmapTff7b72:Tff7b72:Te6edf3deassert_radio_enable_pinsTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tb4b4b4}

Tff7b72void Te6edf3update_radio_lockTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3lora_freq Tff7b72!Tff7b72= T79c0ff0 Tff7b72&Tff7b72& Te6edf3lora_bw Tff7b72!Tff7b72= T79c0ff0 Tff7b72&Tff7b72& Te6edf3lora_txp Tff7b72!Tff7b72= T79c0ff0xFF Tff7b72&Tff7b72& Te6edf3lora_sf Tff7b72!Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{
Te6edf3radio_locked Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3radio_locked Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4}
Tb4b4b4}

Tff7b72bool Te6edf3queue_fullTb4b4b4(Tb4b4b4) Tb4b4b4{ Tff7b72return Tb4b4b4(Te6edf3queue_height Tff7b72>Tff7b72= Te6edf3CONFIG_QUEUE_MAX_LENGTH Tff7b72|Tff7b72| Te6edf3queued_bytes Tff7b72>Tff7b72= Te6edf3CONFIG_QUEUE_SIZETb4b4b4)Tb4b4b4; Tb4b4b4}

Tff7b72volatile Tff7b72bool Te6edf3queue_flushing Tff7b72= Tff7b72falseTb4b4b4;
Tff7b72void Td2a8ffflush_queueTb4b4b4(Tff7b72voidTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3queue_flushingTb4b4b4) Tb4b4b4{
Te6edf3queue_flushing Tff7b72= Tff7b72trueTb4b4b4;
Te6edf3led_tx_onTb4b4b4(Tb4b4b4)Tb4b4b4;

Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52 || MCU_VARIANT == MCU_NATIVE
Tff7b72while Tb4b4b4(Tff7b72!Te6edf3fifo16_isemptyTb4b4b4(Tff7b72&Te6edf3packet_startsTb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72else
Tff7b72while Tb4b4b4(Tff7b72!Te6edf3fifo16_isempty_lockedTb4b4b4(Tff7b72&Te6edf3packet_startsTb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72endif

Tff7b72uint16_t Te6edf3start Tff7b72= Te6edf3fifo16_popTb4b4b4(Tff7b72&Te6edf3packet_startsTb4b4b4)Tb4b4b4;
Tff7b72uint16_t Te6edf3length Tff7b72= Te6edf3fifo16_popTb4b4b4(Tff7b72&Te6edf3packet_lengthsTb4b4b4)Tb4b4b4;

Tff7b72if Tb4b4b4(Te6edf3length Tff7b72>Tff7b72= Te6edf3MIN_L Tff7b72&Tff7b72& Te6edf3length Tff7b72<Tff7b72= Te6edf3MTUTb4b4b4) Tb4b4b4{
Tff7b72for Tb4b4b4(Tff7b72uint16_t Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3i Tff7b72< Te6edf3lengthTb4b4b4; Te6edf3iTff7b72+Tff7b72+Tb4b4b4) Tb4b4b4{
Tff7b72uint16_t Te6edf3pos Tff7b72= Tb4b4b4(Te6edf3startTff7b72+Te6edf3iTb4b4b4)Tff7b72%Te6edf3CONFIG_QUEUE_SIZETb4b4b4;
Te6edf3tbufTb4b4b4[Te6edf3iTb4b4b4] Tff7b72= Te6edf3packet_queueTb4b4b4[Te6edf3posTb4b4b4]Tb4b4b4;
Tb4b4b4}

Te6edf3transmitTb4b4b4(Te6edf3lengthTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}

Te6edf3lora_receiveTb4b4b4(Tb4b4b4)Tb4b4b4; Te6edf3led_tx_offTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}

Te6edf3queue_height Tff7b72= T79c0ff0Tb4b4b4;
Te6edf3queued_bytes Tff7b72= T79c0ff0Tb4b4b4;

Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52 || MCU_VARIANT == MCU_NATIVE
Te6edf3update_airtimeTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif

Te6edf3queue_flushing Tff7b72= Tff7b72falseTb4b4b4;

Tff7b72#Tff7b72if HAS_DISPLAY
Te6edf3display_tx Tff7b72= Tff7b72trueTb4b4b4;
Tff7b72#Tff7b72endif
Tb4b4b4}

Tff7b72void Te6edf3pop_queueTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3queue_flushingTb4b4b4) Tb4b4b4{
Te6edf3queue_flushing Tff7b72= Tff7b72trueTb4b4b4; Te6edf3led_tx_onTb4b4b4(Tb4b4b4)Tb4b4b4;

Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52 || MCU_VARIANT == MCU_NATIVE
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3fifo16_isemptyTb4b4b4(Tff7b72&Te6edf3packet_startsTb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72else
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3fifo16_isempty_lockedTb4b4b4(Tff7b72&Te6edf3packet_startsTb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72endif

Tff7b72uint16_t Te6edf3start Tff7b72= Te6edf3fifo16_popTb4b4b4(Tff7b72&Te6edf3packet_startsTb4b4b4)Tb4b4b4;
Tff7b72uint16_t Te6edf3length Tff7b72= Te6edf3fifo16_popTb4b4b4(Tff7b72&Te6edf3packet_lengthsTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3length Tff7b72>Tff7b72= Te6edf3MIN_L Tff7b72&Tff7b72& Te6edf3length Tff7b72<Tff7b72= Te6edf3MTUTb4b4b4) Tb4b4b4{
Tff7b72for Tb4b4b4(Tff7b72uint16_t Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3i Tff7b72< Te6edf3lengthTb4b4b4; Te6edf3iTff7b72+Tff7b72+Tb4b4b4) Tb4b4b4{
Tff7b72uint16_t Te6edf3pos Tff7b72= Tb4b4b4(Te6edf3startTff7b72+Te6edf3iTb4b4b4)Tff7b72%Te6edf3CONFIG_QUEUE_SIZETb4b4b4;
Te6edf3tbufTb4b4b4[Te6edf3iTb4b4b4] Tff7b72= Te6edf3packet_queueTb4b4b4[Te6edf3posTb4b4b4]Tb4b4b4;
Tb4b4b4}

Te6edf3transmitTb4b4b4(Te6edf3lengthTb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3queue_height Tff7b72-Tff7b72= T79c0ff1Tb4b4b4;
Te6edf3queued_bytes Tff7b72-Tff7b72= Te6edf3lengthTb4b4b4;
Tb4b4b4}

Te6edf3lora_receiveTb4b4b4(Tb4b4b4)Tb4b4b4; Te6edf3led_tx_offTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}

Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52 || MCU_VARIANT == MCU_NATIVE
Te6edf3update_airtimeTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif

Te6edf3queue_flushing Tff7b72= Tff7b72falseTb4b4b4;

Tff7b72#Tff7b72if HAS_DISPLAY
Te6edf3display_tx Tff7b72= Tff7b72trueTb4b4b4;
Tff7b72#Tff7b72endif
Tb4b4b4}

Tff7b72void Te6edf3add_airtimeTb4b4b4(Tff7b72uint16_t Te6edf3writtenTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52 || MCU_VARIANT == MCU_NATIVE
Tff7b72float Te6edf3lora_symbols Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72float Te6edf3packet_cost_ms Tff7b72= T79c0ff0.0Tb4b4b4;
Tff7b72int Te6edf3ldr_opt Tff7b72= T79c0ff0Tb4b4b4; Tff7b72if Tb4b4b4(Te6edf3lora_low_datarateTb4b4b4) Te6edf3ldr_opt Tff7b72= T79c0ff1Tb4b4b4;

Tff7b72#Tff7b72if MODEM == MODEM_RUNTIME
Tff7b72if Tb4b4b4(Te6edf3current_modem Tff7b72=Tff7b72= Te6edf3SX1276 Tff7b72|Tff7b72| Te6edf3current_modem Tff7b72=Tff7b72= Te6edf3SX1278Tb4b4b4) Tb4b4b4{
Te6edf3lora_symbols Tff7b72+Tff7b72= Tb4b4b4(T79c0ff8Tff7b72*Te6edf3written Tff7b72+ Te6edf3PHY_CRC_LORA_BITS Tff7b72- T79c0ff4Tff7b72*Te6edf3lora_sf Tff7b72+ T79c0ff8 Tff7b72+ Te6edf3PHY_HEADER_LORA_SYMBOLSTb4b4b4)Tb4b4b4;
Te6edf3lora_symbols Tff7b72/Tff7b72= T79c0ff4Tff7b72*Tb4b4b4(Te6edf3lora_sfT79c0ff-2Tff7b72*Te6edf3ldr_optTb4b4b4)Tb4b4b4;
Te6edf3lora_symbols Tff7b72*Tff7b72= Te6edf3lora_crTb4b4b4;
Te6edf3lora_symbols Tff7b72+Tff7b72= Te6edf3lora_preamble_symbols Tff7b72+ T79c0ff0.25 Tff7b72+ T79c0ff8Tb4b4b4;
Te6edf3packet_cost_ms Tff7b72+Tff7b72= Te6edf3lora_symbols Tff7b72* Te6edf3lora_symbol_time_msTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{ T8b949e// SX1262 / SX1280
Tff7b72if Tb4b4b4(Te6edf3lora_sf Tff7b72< T79c0ff7Tb4b4b4) Tb4b4b4{
Te6edf3lora_symbols Tff7b72+Tff7b72= Tb4b4b4(T79c0ff8Tff7b72*Te6edf3written Tff7b72+ Te6edf3PHY_CRC_LORA_BITS Tff7b72- T79c0ff4Tff7b72*Te6edf3lora_sf Tff7b72+ Te6edf3PHY_HEADER_LORA_SYMBOLSTb4b4b4)Tb4b4b4;
Te6edf3lora_symbols Tff7b72/Tff7b72= T79c0ff4Tff7b72*Te6edf3lora_sfTb4b4b4;
Te6edf3lora_symbols Tff7b72*Tff7b72= Te6edf3lora_crTb4b4b4;
Te6edf3lora_symbols Tff7b72+Tff7b72= Te6edf3lora_preamble_symbols Tff7b72+ T79c0ff2.25 Tff7b72+ T79c0ff8Tb4b4b4;
Te6edf3packet_cost_ms Tff7b72+Tff7b72= Te6edf3lora_symbols Tff7b72* Te6edf3lora_symbol_time_msTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3lora_symbols Tff7b72+Tff7b72= Tb4b4b4(T79c0ff8Tff7b72*Te6edf3written Tff7b72+ Te6edf3PHY_CRC_LORA_BITS Tff7b72- T79c0ff4Tff7b72*Te6edf3lora_sf Tff7b72+ T79c0ff8 Tff7b72+ Te6edf3PHY_HEADER_LORA_SYMBOLSTb4b4b4)Tb4b4b4;
Te6edf3lora_symbols Tff7b72/Tff7b72= T79c0ff4Tff7b72*Tb4b4b4(Te6edf3lora_sfT79c0ff-2Tff7b72*Te6edf3ldr_optTb4b4b4)Tb4b4b4;
Te6edf3lora_symbols Tff7b72*Tff7b72= Te6edf3lora_crTb4b4b4;
Te6edf3lora_symbols Tff7b72+Tff7b72= Te6edf3lora_preamble_symbols Tff7b72+ T79c0ff0.25 Tff7b72+ T79c0ff8Tb4b4b4;
Te6edf3packet_cost_ms Tff7b72+Tff7b72= Te6edf3lora_symbols Tff7b72* Te6edf3lora_symbol_time_msTb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72#Tff7b72elif MODEM == SX1276 || MODEM == SX1278
Te6edf3lora_symbols Tff7b72+Tff7b72= Tb4b4b4(T79c0ff8Tff7b72*Te6edf3written Tff7b72+ Te6edf3PHY_CRC_LORA_BITS Tff7b72- T79c0ff4Tff7b72*Te6edf3lora_sf Tff7b72+ T79c0ff8 Tff7b72+ Te6edf3PHY_HEADER_LORA_SYMBOLSTb4b4b4)Tb4b4b4;
Te6edf3lora_symbols Tff7b72/Tff7b72= T79c0ff4Tff7b72*Tb4b4b4(Te6edf3lora_sfT79c0ff-2Tff7b72*Te6edf3ldr_optTb4b4b4)Tb4b4b4;
Te6edf3lora_symbols Tff7b72*Tff7b72= Te6edf3lora_crTb4b4b4;
Te6edf3lora_symbols Tff7b72+Tff7b72= Te6edf3lora_preamble_symbols Tff7b72+ T79c0ff0.25 Tff7b72+ T79c0ff8Tb4b4b4;
Te6edf3packet_cost_ms Tff7b72+Tff7b72= Te6edf3lora_symbols Tff7b72* Te6edf3lora_symbol_time_msTb4b4b4;

Tff7b72#Tff7b72elif MODEM == SX1262 || MODEM == SX1280
Tff7b72if Tb4b4b4(Te6edf3lora_sf Tff7b72< T79c0ff7Tb4b4b4) Tb4b4b4{
Te6edf3lora_symbols Tff7b72+Tff7b72= Tb4b4b4(T79c0ff8Tff7b72*Te6edf3written Tff7b72+ Te6edf3PHY_CRC_LORA_BITS Tff7b72- T79c0ff4Tff7b72*Te6edf3lora_sf Tff7b72+ Te6edf3PHY_HEADER_LORA_SYMBOLSTb4b4b4)Tb4b4b4;
Te6edf3lora_symbols Tff7b72/Tff7b72= T79c0ff4Tff7b72*Te6edf3lora_sfTb4b4b4;
Te6edf3lora_symbols Tff7b72*Tff7b72= Te6edf3lora_crTb4b4b4;
Te6edf3lora_symbols Tff7b72+Tff7b72= Te6edf3lora_preamble_symbols Tff7b72+ T79c0ff2.25 Tff7b72+ T79c0ff8Tb4b4b4;
Te6edf3packet_cost_ms Tff7b72+Tff7b72= Te6edf3lora_symbols Tff7b72* Te6edf3lora_symbol_time_msTb4b4b4;

Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3lora_symbols Tff7b72+Tff7b72= Tb4b4b4(T79c0ff8Tff7b72*Te6edf3written Tff7b72+ Te6edf3PHY_CRC_LORA_BITS Tff7b72- T79c0ff4Tff7b72*Te6edf3lora_sf Tff7b72+ T79c0ff8 Tff7b72+ Te6edf3PHY_HEADER_LORA_SYMBOLSTb4b4b4)Tb4b4b4;
Te6edf3lora_symbols Tff7b72/Tff7b72= T79c0ff4Tff7b72*Tb4b4b4(Te6edf3lora_sfT79c0ff-2Tff7b72*Te6edf3ldr_optTb4b4b4)Tb4b4b4;
Te6edf3lora_symbols Tff7b72*Tff7b72= Te6edf3lora_crTb4b4b4;
Te6edf3lora_symbols Tff7b72+Tff7b72= Te6edf3lora_preamble_symbols Tff7b72+ T79c0ff0.25 Tff7b72+ T79c0ff8Tb4b4b4;
Te6edf3packet_cost_ms Tff7b72+Tff7b72= Te6edf3lora_symbols Tff7b72* Te6edf3lora_symbol_time_msTb4b4b4;
Tb4b4b4}

Tff7b72#Tff7b72endif

Tff7b72uint16_t Te6edf3cb Tff7b72= Te6edf3current_airtime_binTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72uint16_t Te6edf3nb Tff7b72= Te6edf3cbTff7b72+T79c0ff1Tb4b4b4; Tff7b72if Tb4b4b4(Te6edf3nb Tff7b72=Tff7b72= Te6edf3AIRTIME_BINSTb4b4b4) Tb4b4b4{ Te6edf3nb Tff7b72= T79c0ff0Tb4b4b4; Tb4b4b4}
Te6edf3airtime_binsTb4b4b4[Te6edf3cbTb4b4b4] Tff7b72+Tff7b72= Te6edf3packet_cost_msTb4b4b4;
Te6edf3airtime_binsTb4b4b4[Te6edf3nbTb4b4b4] Tff7b72= T79c0ff0Tb4b4b4;

Tff7b72#Tff7b72endif
Tb4b4b4}

Tff7b72void Te6edf3update_airtimeTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52 || MCU_VARIANT == MCU_NATIVE
Tff7b72uint16_t Te6edf3cb Tff7b72= Te6edf3current_airtime_binTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72uint16_t Te6edf3pb Tff7b72= Te6edf3cbT79c0ff-1Tb4b4b4; Tff7b72if Tb4b4b4(Te6edf3cbT79c0ff-1 Tff7b72< T79c0ff0Tb4b4b4) Tb4b4b4{ Te6edf3pb Tff7b72= Te6edf3AIRTIME_BINST79c0ff-1Tb4b4b4; Tb4b4b4}
Tff7b72uint16_t Te6edf3nb Tff7b72= Te6edf3cbTff7b72+T79c0ff1Tb4b4b4; Tff7b72if Tb4b4b4(Te6edf3nb Tff7b72=Tff7b72= Te6edf3AIRTIME_BINSTb4b4b4) Tb4b4b4{ Te6edf3nb Tff7b72= T79c0ff0Tb4b4b4; Tb4b4b4}
Te6edf3airtime_binsTb4b4b4[Te6edf3nbTb4b4b4] Tff7b72= T79c0ff0Tb4b4b4; Te6edf3airtime Tff7b72= Tb4b4b4(Tff7b72floatTb4b4b4)Tb4b4b4(Te6edf3airtime_binsTb4b4b4[Te6edf3cbTb4b4b4]Tff7b72+Te6edf3airtime_binsTb4b4b4[Te6edf3pbTb4b4b4]Tb4b4b4)Tff7b72/Tb4b4b4(T79c0ff2.0Tff7b72*Te6edf3AIRTIME_BINLEN_MSTb4b4b4)Tb4b4b4;

Tff7b72uint32_t Te6edf3longterm_airtime_sum Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72uint16_t Te6edf3bin Tff7b72= T79c0ff0Tb4b4b4; Te6edf3bin Tff7b72< Te6edf3AIRTIME_BINSTb4b4b4; Te6edf3binTff7b72+Tff7b72+Tb4b4b4) Tb4b4b4{ Te6edf3longterm_airtime_sum Tff7b72+Tff7b72= Te6edf3airtime_binsTb4b4b4[Te6edf3binTb4b4b4]Tb4b4b4; Tb4b4b4}
Te6edf3longterm_airtime Tff7b72= Tb4b4b4(Tff7b72floatTb4b4b4)Te6edf3longterm_airtime_sumTff7b72/Tb4b4b4(Tff7b72floatTb4b4b4)Te6edf3AIRTIME_LONGTERM_MSTb4b4b4;

Tff7b72float Te6edf3longterm_channel_util_sum Tff7b72= T79c0ff0.0Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72uint16_t Te6edf3bin Tff7b72= T79c0ff0Tb4b4b4; Te6edf3bin Tff7b72< Te6edf3AIRTIME_BINSTb4b4b4; Te6edf3binTff7b72+Tff7b72+Tb4b4b4) Tb4b4b4{ Te6edf3longterm_channel_util_sum Tff7b72+Tff7b72= Te6edf3longterm_binsTb4b4b4[Te6edf3binTb4b4b4]Tb4b4b4; Tb4b4b4}
Te6edf3longterm_channel_util Tff7b72= Tb4b4b4(Tff7b72floatTb4b4b4)Te6edf3longterm_channel_util_sumTff7b72/Tb4b4b4(Tff7b72floatTb4b4b4)Te6edf3AIRTIME_BINSTb4b4b4;

Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52 || MCU_VARIANT == MCU_NATIVE
Te6edf3update_csma_parametersTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif

Te6edf3kiss_indicate_channel_statsTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tb4b4b4}

Tff7b72void Te6edf3transmitTb4b4b4(Tff7b72uint16_t Td2a8ffsizeTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3radio_onlineTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3promiscTb4b4b4) Tb4b4b4{
Tff7b72uint16_t Te6edf3written Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72uint8_t Te6edf3header Tff7b72= Td2a8ffrandomTb4b4b4(T79c0ff256Tb4b4b4) Tff7b72& T79c0ff0xF0Tb4b4b4;
Tff7b72if Tb4b4b4(Td2a8ffsize Tff7b72> Te6edf3SINGLE_MTU Tff7b72- Te6edf3HEADER_LTb4b4b4) Tb4b4b4{ Te6edf3header Tff7b72= Te6edf3header Tff7b72| Te6edf3FLAG_SPLITTb4b4b4; Tb4b4b4}

Te6edf3LoRaTff7b72-Tff7b72>Td2a8ffbeginPacketTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3LoRaTff7b72-Tff7b72>Td2a8ffwriteTb4b4b4(Te6edf3headerTb4b4b4)Tb4b4b4; Te6edf3writtenTff7b72+Tff7b72+Tb4b4b4;

Tff7b72for Tb4b4b4(Tff7b72uint16_t Te6edf3iTff7b72=T79c0ff0Tb4b4b4; Te6edf3i Tff7b72< Td2a8ffsizeTb4b4b4; Te6edf3iTff7b72+Tff7b72+Tb4b4b4) Tb4b4b4{
Te6edf3LoRaTff7b72-Tff7b72>Td2a8ffwriteTb4b4b4(Te6edf3tbufTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4)Tb4b4b4; Te6edf3writtenTff7b72+Tff7b72+Tb4b4b4;

Tff7b72if Tb4b4b4(Te6edf3written Tff7b72=Tff7b72= T79c0ff255 Tff7b72&Tff7b72& Te6edf3isSplitPacketTb4b4b4(Te6edf3headerTb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3LoRaTff7b72-Tff7b72>Td2a8ffendPacketTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3kiss_indicate_errorTb4b4b4(Te6edf3ERROR_MODEM_TIMEOUTTb4b4b4)Tb4b4b4;
Te6edf3kiss_indicate_errorTb4b4b4(Te6edf3ERROR_TXFAILEDTb4b4b4)Tb4b4b4;
Te6edf3led_indicate_errorTb4b4b4(T79c0ff5Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72if MCU_VARIANT == MCU_NATIVE
Tff7b72if Tb4b4b4(Te6edf3native_configTff7b72:Tff7b72:Te6edf3g_configTb4b4b4.Te6edf3reboot_on_tx_failureTb4b4b4) Tb4b4b4{ Te6edf3hard_resetTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72else Tb4b4b4{ Te6edf3LoRaTff7b72-Tff7b72>Te6edf3receiveTb4b4b4(Tb4b4b4)Tb4b4b4; Tff7b72returnTb4b4b4; Tb4b4b4}
Tff7b72#Tff7b72else
Te6edf3hard_resetTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tb4b4b4}

Te6edf3add_airtimeTb4b4b4(Te6edf3writtenTb4b4b4)Tb4b4b4;
Te6edf3LoRaTff7b72-Tff7b72>Td2a8ffbeginPacketTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3LoRaTff7b72-Tff7b72>Td2a8ffwriteTb4b4b4(Te6edf3headerTb4b4b4)Tb4b4b4;
Te6edf3written Tff7b72= T79c0ff1Tb4b4b4;
Te6edf3printfTb4b4b4(Ta5d6ff"Ta5d6ff[radio] Sent %d byte packet (split)Ta5d6ff"Tb4b4b4, Te6edf3writtenTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}

Tff7b72if Tb4b4b4(Tff7b72!Te6edf3LoRaTff7b72-Tff7b72>Td2a8ffendPacketTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3kiss_indicate_errorTb4b4b4(Te6edf3ERROR_MODEM_TIMEOUTTb4b4b4)Tb4b4b4;
Te6edf3kiss_indicate_errorTb4b4b4(Te6edf3ERROR_TXFAILEDTb4b4b4)Tb4b4b4;
Te6edf3led_indicate_errorTb4b4b4(T79c0ff5Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72if MCU_VARIANT == MCU_NATIVE
Tff7b72if Tb4b4b4(Te6edf3native_configTff7b72:Tff7b72:Te6edf3g_configTb4b4b4.Te6edf3reboot_on_tx_failureTb4b4b4) Tb4b4b4{ Te6edf3hard_resetTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72else Tb4b4b4{ Te6edf3LoRaTff7b72-Tff7b72>Te6edf3receiveTb4b4b4(Tb4b4b4)Tb4b4b4; Tff7b72returnTb4b4b4; Tb4b4b4}
Tff7b72#Tff7b72else
Te6edf3hard_resetTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tb4b4b4}

Te6edf3add_airtimeTb4b4b4(Te6edf3writtenTb4b4b4)Tb4b4b4;
Te6edf3printfTb4b4b4(Ta5d6ff"Ta5d6ff[radio] Sent %d byte packetTa5d6ff"Tb4b4b4, Te6edf3writtenTb4b4b4)Tb4b4b4;

Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3led_tx_onTb4b4b4(Tb4b4b4)Tb4b4b4; Tff7b72uint16_t Te6edf3written Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72if Tb4b4b4(Td2a8ffsize Tff7b72> Te6edf3SINGLE_MTUTb4b4b4) Tb4b4b4{ Td2a8ffsize Tff7b72= Te6edf3SINGLE_MTUTb4b4b4; Tb4b4b4}
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3implicitTb4b4b4) Tb4b4b4{ Te6edf3LoRaTff7b72-Tff7b72>Td2a8ffbeginPacketTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72else Tb4b4b4{ Te6edf3LoRaTff7b72-Tff7b72>Td2a8ffbeginPacketTb4b4b4(Td2a8ffsizeTb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72for Tb4b4b4(Tff7b72uint16_t Te6edf3iTff7b72=T79c0ff0Tb4b4b4; Te6edf3i Tff7b72< Td2a8ffsizeTb4b4b4; Te6edf3iTff7b72+Tff7b72+Tb4b4b4) Tb4b4b4{ Te6edf3LoRaTff7b72-Tff7b72>Td2a8ffwriteTb4b4b4(Te6edf3tbufTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4)Tb4b4b4; Te6edf3writtenTff7b72+Tff7b72+Tb4b4b4; Tb4b4b4}
Te6edf3LoRaTff7b72-Tff7b72>Td2a8ffendPacketTb4b4b4(Tb4b4b4)Tb4b4b4; Te6edf3add_airtimeTb4b4b4(Te6edf3writtenTb4b4b4)Tb4b4b4;
Te6edf3printfTb4b4b4(Ta5d6ff"Ta5d6ff[radio] Sent %d byte packetTa5d6ff"Tb4b4b4, Te6edf3writtenTb4b4b4)Tb4b4b4;
Tb4b4b4}

Tb4b4b4} Tff7b72else Tb4b4b4{ Te6edf3kiss_indicate_errorTb4b4b4(Te6edf3ERROR_TXFAILEDTb4b4b4)Tb4b4b4; Te6edf3led_indicate_errorTb4b4b4(T79c0ff5Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4}

Tff7b72void Te6edf3serial_callbackTb4b4b4(Tff7b72uint8_t Te6edf3sbyteTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3IN_FRAME Tff7b72&Tff7b72& Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3FEND Tff7b72&Tff7b72& Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_DATATb4b4b4) Tb4b4b4{
Te6edf3IN_FRAME Tff7b72= Tff7b72falseTb4b4b4;

Tff7b72if Tb4b4b4(Tff7b72!Te6edf3fifo16_isfullTb4b4b4(Tff7b72&Te6edf3packet_startsTb4b4b4) Tff7b72&Tff7b72& Te6edf3queued_bytes Tff7b72< Te6edf3CONFIG_QUEUE_SIZETb4b4b4) Tb4b4b4{
Tff7b72uint16_t Te6edf3s Tff7b72= Te6edf3current_packet_startTb4b4b4;
Tff7b72int16_t Te6edf3e Tff7b72= Te6edf3queue_cursorT79c0ff-1Tb4b4b4; Tff7b72if Tb4b4b4(Te6edf3e Tff7b72=Tff7b72= T79c0ff-1Tb4b4b4) Te6edf3e Tff7b72= Te6edf3CONFIG_QUEUE_SIZET79c0ff-1Tb4b4b4;
Tff7b72uint16_t Te6edf3lTb4b4b4;

Tff7b72if Tb4b4b4(Te6edf3s Tff7b72!Tff7b72= Te6edf3eTb4b4b4) Tb4b4b4{ Te6edf3l Tff7b72= Tb4b4b4(Te6edf3s Tff7b72< Te6edf3eTb4b4b4) Tff7b72? Te6edf3e Tff7b72- Te6edf3s Tff7b72+ T79c0ff1 Tff7b72: Te6edf3CONFIG_QUEUE_SIZE Tff7b72- Te6edf3s Tff7b72+ Te6edf3e Tff7b72+ T79c0ff1Tb4b4b4; Tb4b4b4}
Tff7b72else Tb4b4b4{ Te6edf3l Tff7b72= T79c0ff1Tb4b4b4; Tb4b4b4}

Tff7b72if Tb4b4b4(Te6edf3l Tff7b72>Tff7b72= Te6edf3MIN_LTb4b4b4) Tb4b4b4{
Te6edf3queue_heightTff7b72+Tff7b72+Tb4b4b4;
Te6edf3fifo16_pushTb4b4b4(Tff7b72&Te6edf3packet_startsTb4b4b4, Te6edf3sTb4b4b4)Tb4b4b4;
Te6edf3fifo16_pushTb4b4b4(Tff7b72&Te6edf3packet_lengthsTb4b4b4, Te6edf3lTb4b4b4)Tb4b4b4;
Te6edf3current_packet_start Tff7b72= Te6edf3queue_cursorTb4b4b4;
Tb4b4b4}
Tb4b4b4}

Tff7b72#Tff7b72ifdef HAS_PROVISIONING
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3IN_FRAME Tff7b72&Tff7b72& Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3FEND Tff7b72&Tff7b72& Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_PROVISION_REQTb4b4b4) Tb4b4b4{
Te6edf3IN_FRAME Tff7b72= Tff7b72falseTb4b4b4;
Te6edf3on_provision_requestTb4b4b4(Te6edf3provision_rx_bufTb4b4b4)Tb4b4b4;
Te6edf3provision_rx_bufTb4b4b4.Td2a8ffclearTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3FENDTb4b4b4) Tb4b4b4{
Te6edf3IN_FRAME Tff7b72= Tff7b72trueTb4b4b4;
Te6edf3command Tff7b72= Te6edf3CMD_UNKNOWNTb4b4b4;
Te6edf3frame_len Tff7b72= T79c0ff0Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3IN_FRAME Tff7b72&Tff7b72& Te6edf3frame_len Tff7b72< Te6edf3MTUTb4b4b4) Tb4b4b4{
T8b949e// Have a look at the command byte first
Tff7b72if Tb4b4b4(Te6edf3frame_len Tff7b72=Tff7b72= T79c0ff0 Tff7b72&Tff7b72& Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_UNKNOWNTb4b4b4) Tb4b4b4{
Te6edf3command Tff7b72= Te6edf3sbyteTb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_DATATb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3bt_state Tff7b72!Tff7b72= Te6edf3BT_STATE_CONNECTEDTb4b4b4) Tb4b4b4{
Te6edf3cable_state Tff7b72= Te6edf3CABLE_STATE_CONNECTEDTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3FESCTb4b4b4) Tb4b4b4{
Te6edf3ESCAPE Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3ESCAPETb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFENDTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FENDTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFESCTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FESCTb4b4b4;
Te6edf3ESCAPE Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3queue_height Tff7b72< Te6edf3CONFIG_QUEUE_MAX_LENGTH Tff7b72&Tff7b72& Te6edf3queued_bytes Tff7b72< Te6edf3CONFIG_QUEUE_SIZETb4b4b4) Tb4b4b4{
Te6edf3queued_bytesTff7b72+Tff7b72+Tb4b4b4;
Te6edf3packet_queueTb4b4b4[Te6edf3queue_cursorTff7b72+Tff7b72+Tb4b4b4] Tff7b72= Te6edf3sbyteTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3queue_cursor Tff7b72=Tff7b72= Te6edf3CONFIG_QUEUE_SIZETb4b4b4) Te6edf3queue_cursor Tff7b72= T79c0ff0Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72#Tff7b72ifdef HAS_PROVISIONING
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_PROVISION_REQTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3FESCTb4b4b4) Tb4b4b4{
Te6edf3ESCAPE Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3ESCAPETb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFENDTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FENDTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFESCTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FESCTb4b4b4;
Te6edf3ESCAPE Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3provision_rx_bufTb4b4b4.Td2a8ffsizeTb4b4b4(Tb4b4b4) Tff7b72< Te6edf3PROVISION_RX_BUF_MAXTb4b4b4) Tb4b4b4{
Te6edf3provision_rx_bufTb4b4b4.Te6edf3appendTb4b4b4(Te6edf3sbyteTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_FREQUENCYTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3FESCTb4b4b4) Tb4b4b4{
Te6edf3ESCAPE Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3ESCAPETb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFENDTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FENDTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFESCTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FESCTb4b4b4;
Te6edf3ESCAPE Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3frame_len Tff7b72< Te6edf3CMD_LTb4b4b4) Te6edf3cmdbufTb4b4b4[Te6edf3frame_lenTff7b72+Tff7b72+Tb4b4b4] Tff7b72= Te6edf3sbyteTb4b4b4;
Tb4b4b4}

Tff7b72if Tb4b4b4(Te6edf3frame_len Tff7b72=Tff7b72= T79c0ff4Tb4b4b4) Tb4b4b4{
Tff7b72uint32_t Te6edf3freq Tff7b72= Tb4b4b4(Tff7b72uint32_tTb4b4b4)Te6edf3cmdbufTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72<Tff7b72< T79c0ff24 Tff7b72| Tb4b4b4(Tff7b72uint32_tTb4b4b4)Te6edf3cmdbufTb4b4b4[T79c0ff1Tb4b4b4] Tff7b72<Tff7b72< T79c0ff16 Tff7b72| Tb4b4b4(Tff7b72uint32_tTb4b4b4)Te6edf3cmdbufTb4b4b4[T79c0ff2Tb4b4b4] Tff7b72<Tff7b72< T79c0ff8 Tff7b72| Tb4b4b4(Tff7b72uint32_tTb4b4b4)Te6edf3cmdbufTb4b4b4[T79c0ff3Tb4b4b4]Tb4b4b4;

Tff7b72if Tb4b4b4(Te6edf3freq Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{
Te6edf3kiss_indicate_frequencyTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3lora_freq Tff7b72= Te6edf3freqTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3op_mode Tff7b72=Tff7b72= Te6edf3MODE_HOSTTb4b4b4) Te6edf3setFrequencyTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3kiss_indicate_frequencyTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_BANDWIDTHTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3FESCTb4b4b4) Tb4b4b4{
Te6edf3ESCAPE Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3ESCAPETb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFENDTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FENDTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFESCTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FESCTb4b4b4;
Te6edf3ESCAPE Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3frame_len Tff7b72< Te6edf3CMD_LTb4b4b4) Te6edf3cmdbufTb4b4b4[Te6edf3frame_lenTff7b72+Tff7b72+Tb4b4b4] Tff7b72= Te6edf3sbyteTb4b4b4;
Tb4b4b4}

Tff7b72if Tb4b4b4(Te6edf3frame_len Tff7b72=Tff7b72= T79c0ff4Tb4b4b4) Tb4b4b4{
Tff7b72uint32_t Te6edf3bw Tff7b72= Tb4b4b4(Tff7b72uint32_tTb4b4b4)Te6edf3cmdbufTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72<Tff7b72< T79c0ff24 Tff7b72| Tb4b4b4(Tff7b72uint32_tTb4b4b4)Te6edf3cmdbufTb4b4b4[T79c0ff1Tb4b4b4] Tff7b72<Tff7b72< T79c0ff16 Tff7b72| Tb4b4b4(Tff7b72uint32_tTb4b4b4)Te6edf3cmdbufTb4b4b4[T79c0ff2Tb4b4b4] Tff7b72<Tff7b72< T79c0ff8 Tff7b72| Tb4b4b4(Tff7b72uint32_tTb4b4b4)Te6edf3cmdbufTb4b4b4[T79c0ff3Tb4b4b4]Tb4b4b4;

Tff7b72if Tb4b4b4(Te6edf3bw Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{
Te6edf3kiss_indicate_bandwidthTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3lora_bw Tff7b72= Te6edf3bwTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3op_mode Tff7b72=Tff7b72= Te6edf3MODE_HOSTTb4b4b4) Te6edf3setBandwidthTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3kiss_indicate_bandwidthTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_TXPOWERTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= T79c0ff0xFFTb4b4b4) Tb4b4b4{
Te6edf3kiss_indicate_txpowerTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72int Te6edf3txp Tff7b72= Te6edf3sbyteTb4b4b4;
Tff7b72#Tff7b72if MODEM == MODEM_RUNTIME
Tff7b72if Tb4b4b4(Te6edf3current_modem Tff7b72=Tff7b72= Te6edf3SX1262Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3txp Tff7b72> T79c0ff22Tb4b4b4) Te6edf3txp Tff7b72= T79c0ff22Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3current_modem Tff7b72=Tff7b72= Te6edf3SX1280Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3txp Tff7b72> T79c0ff13Tb4b4b4) Te6edf3txp Tff7b72= T79c0ff13Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3txp Tff7b72> T79c0ff17Tb4b4b4) Te6edf3txp Tff7b72= T79c0ff17Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72elif MODEM == SX1262
Tff7b72#Tff7b72if HAS_LORA_PA
Tff7b72if Tb4b4b4(Te6edf3txp Tff7b72> Te6edf3PA_MAX_OUTPUTTb4b4b4) Te6edf3txp Tff7b72= Te6edf3PA_MAX_OUTPUTTb4b4b4;
Tff7b72#Tff7b72else
Tff7b72if Tb4b4b4(Te6edf3txp Tff7b72> T79c0ff22Tb4b4b4) Te6edf3txp Tff7b72= T79c0ff22Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72elif MODEM == SX1280
Tff7b72#Tff7b72if HAS_PA
Tff7b72if Tb4b4b4(Te6edf3txp Tff7b72> T79c0ff20Tb4b4b4) Te6edf3txp Tff7b72= T79c0ff20Tb4b4b4;
Tff7b72#Tff7b72else
Tff7b72if Tb4b4b4(Te6edf3txp Tff7b72> T79c0ff13Tb4b4b4) Te6edf3txp Tff7b72= T79c0ff13Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72else
Tff7b72if Tb4b4b4(Te6edf3txp Tff7b72> T79c0ff17Tb4b4b4) Te6edf3txp Tff7b72= T79c0ff17Tb4b4b4;
Tff7b72#Tff7b72endif

Te6edf3lora_txp Tff7b72= Te6edf3txpTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3op_mode Tff7b72=Tff7b72= Te6edf3MODE_HOSTTb4b4b4) Te6edf3setTXPowerTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3kiss_indicate_txpowerTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_SFTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= T79c0ff0xFFTb4b4b4) Tb4b4b4{
Te6edf3kiss_indicate_spreadingfactorTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72int Te6edf3sf Tff7b72= Te6edf3sbyteTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3sf Tff7b72< T79c0ff5Tb4b4b4) Te6edf3sf Tff7b72= T79c0ff5Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3sf Tff7b72> T79c0ff12Tb4b4b4) Te6edf3sf Tff7b72= T79c0ff12Tb4b4b4;

Te6edf3lora_sf Tff7b72= Te6edf3sfTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3op_mode Tff7b72=Tff7b72= Te6edf3MODE_HOSTTb4b4b4) Te6edf3setSpreadingFactorTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3kiss_indicate_spreadingfactorTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_CRTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= T79c0ff0xFFTb4b4b4) Tb4b4b4{
Te6edf3kiss_indicate_codingrateTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72int Te6edf3cr Tff7b72= Te6edf3sbyteTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3cr Tff7b72< T79c0ff5Tb4b4b4) Te6edf3cr Tff7b72= T79c0ff5Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3cr Tff7b72> T79c0ff8Tb4b4b4) Te6edf3cr Tff7b72= T79c0ff8Tb4b4b4;

Te6edf3lora_cr Tff7b72= Te6edf3crTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3op_mode Tff7b72=Tff7b72= Te6edf3MODE_HOSTTb4b4b4) Te6edf3setCodingRateTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3kiss_indicate_codingrateTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_IMPLICITTb4b4b4) Tb4b4b4{
Te6edf3set_implicit_lengthTb4b4b4(Te6edf3sbyteTb4b4b4)Tb4b4b4;
Te6edf3kiss_indicate_implicit_lengthTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_LEAVETb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= T79c0ff0xFFTb4b4b4) Tb4b4b4{
Te6edf3display_unblankTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3cable_state Tff7b72= Te6edf3CABLE_STATE_DISCONNECTEDTb4b4b4;
Te6edf3current_rssi Tff7b72= T79c0ff-292Tb4b4b4;
Te6edf3last_rssi Tff7b72= T79c0ff-292Tb4b4b4;
Te6edf3last_rssi_raw Tff7b72= T79c0ff0x00Tb4b4b4;
Te6edf3last_snr_raw Tff7b72= T79c0ff0x80Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_RADIO_STATETb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3bt_state Tff7b72!Tff7b72= Te6edf3BT_STATE_CONNECTEDTb4b4b4) Tb4b4b4{
Te6edf3cable_state Tff7b72= Te6edf3CABLE_STATE_CONNECTEDTb4b4b4;
Te6edf3display_unblankTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= T79c0ff0xFFTb4b4b4) Tb4b4b4{
Te6edf3kiss_indicate_radiostateTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= T79c0ff0x00Tb4b4b4) Tb4b4b4{
Te6edf3stopRadioTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3kiss_indicate_radiostateTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= T79c0ff0x01Tb4b4b4) Tb4b4b4{
Te6edf3startRadioTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3kiss_indicate_radiostateTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_ST_ALOCKTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3FESCTb4b4b4) Tb4b4b4{
Te6edf3ESCAPE Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3ESCAPETb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFENDTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FENDTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFESCTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FESCTb4b4b4;
Te6edf3ESCAPE Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3frame_len Tff7b72< Te6edf3CMD_LTb4b4b4) Te6edf3cmdbufTb4b4b4[Te6edf3frame_lenTff7b72+Tff7b72+Tb4b4b4] Tff7b72= Te6edf3sbyteTb4b4b4;
Tb4b4b4}

Tff7b72if Tb4b4b4(Te6edf3frame_len Tff7b72=Tff7b72= T79c0ff2Tb4b4b4) Tb4b4b4{
Tff7b72uint16_t Te6edf3at Tff7b72= Tb4b4b4(Tff7b72uint16_tTb4b4b4)Te6edf3cmdbufTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72<Tff7b72< T79c0ff8 Tff7b72| Tb4b4b4(Tff7b72uint16_tTb4b4b4)Te6edf3cmdbufTb4b4b4[T79c0ff1Tb4b4b4]Tb4b4b4;

Tff7b72if Tb4b4b4(Te6edf3at Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{
Te6edf3st_airtime_limit Tff7b72= T79c0ff0.0Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3st_airtime_limit Tff7b72= Tb4b4b4(Tff7b72floatTb4b4b4)Te6edf3atTff7b72/Tb4b4b4(T79c0ff100.0Tff7b72*T79c0ff100.0Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3st_airtime_limit Tff7b72>Tff7b72= T79c0ff1.0Tb4b4b4) Tb4b4b4{ Te6edf3st_airtime_limit Tff7b72= T79c0ff0.0Tb4b4b4; Tb4b4b4}
Tb4b4b4}
Te6edf3kiss_indicate_st_alockTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_LT_ALOCKTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3FESCTb4b4b4) Tb4b4b4{
Te6edf3ESCAPE Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3ESCAPETb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFENDTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FENDTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFESCTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FESCTb4b4b4;
Te6edf3ESCAPE Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3frame_len Tff7b72< Te6edf3CMD_LTb4b4b4) Te6edf3cmdbufTb4b4b4[Te6edf3frame_lenTff7b72+Tff7b72+Tb4b4b4] Tff7b72= Te6edf3sbyteTb4b4b4;
Tb4b4b4}

Tff7b72if Tb4b4b4(Te6edf3frame_len Tff7b72=Tff7b72= T79c0ff2Tb4b4b4) Tb4b4b4{
Tff7b72uint16_t Te6edf3at Tff7b72= Tb4b4b4(Tff7b72uint16_tTb4b4b4)Te6edf3cmdbufTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72<Tff7b72< T79c0ff8 Tff7b72| Tb4b4b4(Tff7b72uint16_tTb4b4b4)Te6edf3cmdbufTb4b4b4[T79c0ff1Tb4b4b4]Tb4b4b4;

Tff7b72if Tb4b4b4(Te6edf3at Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{
Te6edf3lt_airtime_limit Tff7b72= T79c0ff0.0Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3lt_airtime_limit Tff7b72= Tb4b4b4(Tff7b72floatTb4b4b4)Te6edf3atTff7b72/Tb4b4b4(T79c0ff100.0Tff7b72*T79c0ff100.0Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3lt_airtime_limit Tff7b72>Tff7b72= T79c0ff1.0Tb4b4b4) Tb4b4b4{ Te6edf3lt_airtime_limit Tff7b72= T79c0ff0.0Tb4b4b4; Tb4b4b4}
Tb4b4b4}
Te6edf3kiss_indicate_lt_alockTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_STAT_RXTb4b4b4) Tb4b4b4{
Te6edf3kiss_indicate_stat_rxTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_STAT_TXTb4b4b4) Tb4b4b4{
Te6edf3kiss_indicate_stat_txTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_STAT_RSSITb4b4b4) Tb4b4b4{
Te6edf3kiss_indicate_stat_rssiTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_RADIO_LOCKTb4b4b4) Tb4b4b4{
Te6edf3update_radio_lockTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3kiss_indicate_radio_lockTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_BLINKTb4b4b4) Tb4b4b4{
Te6edf3led_indicate_infoTb4b4b4(Te6edf3sbyteTb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_RANDOMTb4b4b4) Tb4b4b4{
Te6edf3kiss_indicate_randomTb4b4b4(Te6edf3getRandomTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_DETECTTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3DETECT_REQTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3bt_state Tff7b72!Tff7b72= Te6edf3BT_STATE_CONNECTEDTb4b4b4) Te6edf3cable_state Tff7b72= Te6edf3CABLE_STATE_CONNECTEDTb4b4b4;
Te6edf3kiss_indicate_detectTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_PROMISCTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= T79c0ff0x01Tb4b4b4) Tb4b4b4{
Te6edf3promisc_enableTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= T79c0ff0x00Tb4b4b4) Tb4b4b4{
Te6edf3promisc_disableTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3kiss_indicate_promiscTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_READYTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3queue_fullTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3kiss_indicate_readyTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3kiss_indicate_not_readyTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_UNLOCK_ROMTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3ROM_UNLOCK_BYTETb4b4b4) Tb4b4b4{
Te6edf3unlock_romTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_RESETTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3CMD_RESET_BYTETb4b4b4) Tb4b4b4{
Te6edf3hard_resetTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_ROM_READTb4b4b4) Tb4b4b4{
Te6edf3kiss_dump_eepromTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_CFG_READTb4b4b4) Tb4b4b4{
Te6edf3kiss_dump_configTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_ROM_WRITETb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3FESCTb4b4b4) Tb4b4b4{
Te6edf3ESCAPE Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3ESCAPETb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFENDTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FENDTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFESCTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FESCTb4b4b4;
Te6edf3ESCAPE Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3frame_len Tff7b72< Te6edf3CMD_LTb4b4b4) Te6edf3cmdbufTb4b4b4[Te6edf3frame_lenTff7b72+Tff7b72+Tb4b4b4] Tff7b72= Te6edf3sbyteTb4b4b4;
Tb4b4b4}

Tff7b72if Tb4b4b4(Te6edf3frame_len Tff7b72=Tff7b72= T79c0ff2Tb4b4b4) Tb4b4b4{
Te6edf3eeprom_writeTb4b4b4(Te6edf3cmdbufTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4, Te6edf3cmdbufTb4b4b4[T79c0ff1Tb4b4b4]Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_FW_VERSIONTb4b4b4) Tb4b4b4{
Te6edf3kiss_indicate_versionTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_PLATFORMTb4b4b4) Tb4b4b4{
Te6edf3kiss_indicate_platformTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_MCUTb4b4b4) Tb4b4b4{
Te6edf3kiss_indicate_mcuTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_BOARDTb4b4b4) Tb4b4b4{
Te6edf3kiss_indicate_boardTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_CONF_SAVETb4b4b4) Tb4b4b4{
Te6edf3eeprom_conf_saveTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_CONF_DELETETb4b4b4) Tb4b4b4{
Te6edf3eeprom_conf_deleteTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_FB_EXTTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if HAS_DISPLAY == true
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= T79c0ff0xFFTb4b4b4) Tb4b4b4{
Te6edf3kiss_indicate_fbstateTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= T79c0ff0x00Tb4b4b4) Tb4b4b4{
Te6edf3ext_fb_disableTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3kiss_indicate_fbstateTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= T79c0ff0x01Tb4b4b4) Tb4b4b4{
Te6edf3ext_fb_enableTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3kiss_indicate_fbstateTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_FB_WRITETb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3FESCTb4b4b4) Tb4b4b4{
Te6edf3ESCAPE Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3ESCAPETb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFENDTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FENDTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFESCTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FESCTb4b4b4;
Te6edf3ESCAPE Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3frame_len Tff7b72< Te6edf3CMD_LTb4b4b4) Te6edf3cmdbufTb4b4b4[Te6edf3frame_lenTff7b72+Tff7b72+Tb4b4b4] Tff7b72= Te6edf3sbyteTb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72if HAS_DISPLAY
Tff7b72if Tb4b4b4(Te6edf3frame_len Tff7b72=Tff7b72= T79c0ff9Tb4b4b4) Tb4b4b4{
Tff7b72uint8_t Td2a8ffline Tff7b72= Te6edf3cmdbufTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4;
Tff7b72if Tb4b4b4(Td2a8ffline Tff7b72> T79c0ff63Tb4b4b4) Td2a8ffline Tff7b72= T79c0ff63Tb4b4b4;
Tff7b72int Te6edf3fb_o Tff7b72= Td2a8fflineTff7b72*T79c0ff8Tb4b4b4;
Te6edf3memcpyTb4b4b4(Te6edf3fbTff7b72+Te6edf3fb_oTb4b4b4, Te6edf3cmdbufTff7b72+T79c0ff1Tb4b4b4, T79c0ff8Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_FB_READTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72!Tff7b72= T79c0ff0x00Tb4b4b4) Tb4b4b4{ Te6edf3kiss_indicate_fbTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_DISP_READTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72!Tff7b72= T79c0ff0x00Tb4b4b4) Tb4b4b4{ Te6edf3kiss_indicate_dispTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_DEV_HASHTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52 || MCU_VARIANT == MCU_NATIVE
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72!Tff7b72= T79c0ff0x00Tb4b4b4) Tb4b4b4{
Te6edf3kiss_indicate_device_hashTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_DEV_SIGTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52 || MCU_VARIANT == MCU_NATIVE
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3FESCTb4b4b4) Tb4b4b4{
Te6edf3ESCAPE Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3ESCAPETb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFENDTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FENDTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFESCTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FESCTb4b4b4;
Te6edf3ESCAPE Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3frame_len Tff7b72< Te6edf3CMD_LTb4b4b4) Te6edf3cmdbufTb4b4b4[Te6edf3frame_lenTff7b72+Tff7b72+Tb4b4b4] Tff7b72= Te6edf3sbyteTb4b4b4;
Tb4b4b4}

Tff7b72if Tb4b4b4(Te6edf3frame_len Tff7b72=Tff7b72= Te6edf3DEV_SIG_LENTb4b4b4) Tb4b4b4{
Te6edf3memcpyTb4b4b4(Te6edf3dev_sigTb4b4b4, Te6edf3cmdbufTb4b4b4, Te6edf3DEV_SIG_LENTb4b4b4)Tb4b4b4;
Te6edf3device_save_signatureTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_FW_UPDTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= T79c0ff0x01Tb4b4b4) Tb4b4b4{
Te6edf3firmware_update_mode Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3firmware_update_mode Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_HASHESTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52 || MCU_VARIANT == MCU_NATIVE
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= T79c0ff0x01Tb4b4b4) Tb4b4b4{
Te6edf3kiss_indicate_target_fw_hashTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= T79c0ff0x02Tb4b4b4) Tb4b4b4{
Te6edf3kiss_indicate_fw_hashTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= T79c0ff0x03Tb4b4b4) Tb4b4b4{
Te6edf3kiss_indicate_bootloader_hashTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= T79c0ff0x04Tb4b4b4) Tb4b4b4{
Te6edf3kiss_indicate_partition_table_hashTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_FW_HASHTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52 || MCU_VARIANT == MCU_NATIVE
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3FESCTb4b4b4) Tb4b4b4{
Te6edf3ESCAPE Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3ESCAPETb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFENDTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FENDTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFESCTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FESCTb4b4b4;
Te6edf3ESCAPE Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3frame_len Tff7b72< Te6edf3CMD_LTb4b4b4) Te6edf3cmdbufTb4b4b4[Te6edf3frame_lenTff7b72+Tff7b72+Tb4b4b4] Tff7b72= Te6edf3sbyteTb4b4b4;
Tb4b4b4}

Tff7b72if Tb4b4b4(Te6edf3frame_len Tff7b72=Tff7b72= Te6edf3DEV_HASH_LENTb4b4b4) Tb4b4b4{
Te6edf3memcpyTb4b4b4(Te6edf3dev_firmware_hash_targetTb4b4b4, Te6edf3cmdbufTb4b4b4, Te6edf3DEV_HASH_LENTb4b4b4)Tb4b4b4;
Te6edf3device_save_firmware_hashTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_WIFI_CHNTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if HAS_WIFI
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72> T79c0ff0 Tff7b72&Tff7b72& Te6edf3sbyte Tff7b72< T79c0ff14Tb4b4b4) Tb4b4b4{ Te6edf3eeprom_updateTb4b4b4(Te6edf3eeprom_addrTb4b4b4(Te6edf3ADDR_CONF_WCHNTb4b4b4)Tb4b4b4, Te6edf3sbyteTb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_WIFI_MODETb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if HAS_WIFI
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3WR_WIFI_OFF Tff7b72|Tff7b72| Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3WR_WIFI_STA Tff7b72|Tff7b72| Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3WR_WIFI_APTb4b4b4) Tb4b4b4{
Te6edf3wr_conf_saveTb4b4b4(Te6edf3sbyteTb4b4b4)Tb4b4b4;
Te6edf3wifi_mode Tff7b72= Te6edf3sbyteTb4b4b4;
Te6edf3wifi_remote_initTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_WIFI_SSIDTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if HAS_WIFI
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3FESCTb4b4b4) Tb4b4b4{ Te6edf3ESCAPE Tff7b72= Tff7b72trueTb4b4b4; Tb4b4b4}
Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3ESCAPETb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFENDTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FENDTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFESCTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FESCTb4b4b4;
Te6edf3ESCAPE Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3frame_len Tff7b72< Te6edf3CMD_LTb4b4b4) Te6edf3cmdbufTb4b4b4[Te6edf3frame_lenTff7b72+Tff7b72+Tb4b4b4] Tff7b72= Te6edf3sbyteTb4b4b4;
Tb4b4b4}

Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= T79c0ff0x00Tb4b4b4) Tb4b4b4{
Tff7b72for Tb4b4b4(Tff7b72uint8_t Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3iTff7b72<T79c0ff33Tb4b4b4; Te6edf3iTff7b72+Tff7b72+Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3iTff7b72<Te6edf3frame_len Tff7b72&Tff7b72& Te6edf3iTff7b72<T79c0ff32Tb4b4b4) Tb4b4b4{ Te6edf3eeprom_updateTb4b4b4(Te6edf3config_addrTb4b4b4(Te6edf3ADDR_CONF_SSIDTff7b72+Te6edf3iTb4b4b4)Tb4b4b4, Te6edf3cmdbufTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72else Tb4b4b4{ Te6edf3eeprom_updateTb4b4b4(Te6edf3config_addrTb4b4b4(Te6edf3ADDR_CONF_SSIDTff7b72+Te6edf3iTb4b4b4)Tb4b4b4, T79c0ff0x00Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_WIFI_PSKTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if HAS_WIFI
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3FESCTb4b4b4) Tb4b4b4{ Te6edf3ESCAPE Tff7b72= Tff7b72trueTb4b4b4; Tb4b4b4}
Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3ESCAPETb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFENDTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FENDTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFESCTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FESCTb4b4b4;
Te6edf3ESCAPE Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3frame_len Tff7b72< Te6edf3CMD_LTb4b4b4) Te6edf3cmdbufTb4b4b4[Te6edf3frame_lenTff7b72+Tff7b72+Tb4b4b4] Tff7b72= Te6edf3sbyteTb4b4b4;
Tb4b4b4}

Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= T79c0ff0x00Tb4b4b4) Tb4b4b4{
Tff7b72for Tb4b4b4(Tff7b72uint8_t Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3iTff7b72<T79c0ff33Tb4b4b4; Te6edf3iTff7b72+Tff7b72+Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3iTff7b72<Te6edf3frame_len Tff7b72&Tff7b72& Te6edf3iTff7b72<T79c0ff32Tb4b4b4) Tb4b4b4{ Te6edf3eeprom_updateTb4b4b4(Te6edf3config_addrTb4b4b4(Te6edf3ADDR_CONF_PSKTff7b72+Te6edf3iTb4b4b4)Tb4b4b4, Te6edf3cmdbufTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72else Tb4b4b4{ Te6edf3eeprom_updateTb4b4b4(Te6edf3config_addrTb4b4b4(Te6edf3ADDR_CONF_PSKTff7b72+Te6edf3iTb4b4b4)Tb4b4b4, T79c0ff0x00Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_WIFI_IPTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if HAS_WIFI
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3FESCTb4b4b4) Tb4b4b4{ Te6edf3ESCAPE Tff7b72= Tff7b72trueTb4b4b4; Tb4b4b4}
Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3ESCAPETb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFENDTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FENDTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFESCTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FESCTb4b4b4;
Te6edf3ESCAPE Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3frame_len Tff7b72< Te6edf3CMD_LTb4b4b4) Te6edf3cmdbufTb4b4b4[Te6edf3frame_lenTff7b72+Tff7b72+Tb4b4b4] Tff7b72= Te6edf3sbyteTb4b4b4;
Tb4b4b4}

Tff7b72if Tb4b4b4(Te6edf3frame_len Tff7b72=Tff7b72= T79c0ff4Tb4b4b4) Tb4b4b4{ Tff7b72for Tb4b4b4(Tff7b72uint8_t Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3iTff7b72<T79c0ff4Tb4b4b4; Te6edf3iTff7b72+Tff7b72+Tb4b4b4) Tb4b4b4{ Te6edf3eeprom_updateTb4b4b4(Te6edf3config_addrTb4b4b4(Te6edf3ADDR_CONF_IPTff7b72+Te6edf3iTb4b4b4)Tb4b4b4, Te6edf3cmdbufTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4)Tb4b4b4; Tb4b4b4} Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_WIFI_NMTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if HAS_WIFI
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3FESCTb4b4b4) Tb4b4b4{ Te6edf3ESCAPE Tff7b72= Tff7b72trueTb4b4b4; Tb4b4b4}
Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3ESCAPETb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFENDTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FENDTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFESCTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FESCTb4b4b4;
Te6edf3ESCAPE Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3frame_len Tff7b72< Te6edf3CMD_LTb4b4b4) Te6edf3cmdbufTb4b4b4[Te6edf3frame_lenTff7b72+Tff7b72+Tb4b4b4] Tff7b72= Te6edf3sbyteTb4b4b4;
Tb4b4b4}

Tff7b72if Tb4b4b4(Te6edf3frame_len Tff7b72=Tff7b72= T79c0ff4Tb4b4b4) Tb4b4b4{ Tff7b72for Tb4b4b4(Tff7b72uint8_t Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3iTff7b72<T79c0ff4Tb4b4b4; Te6edf3iTff7b72+Tff7b72+Tb4b4b4) Tb4b4b4{ Te6edf3eeprom_updateTb4b4b4(Te6edf3config_addrTb4b4b4(Te6edf3ADDR_CONF_NMTff7b72+Te6edf3iTb4b4b4)Tb4b4b4, Te6edf3cmdbufTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4)Tb4b4b4; Tb4b4b4} Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_BT_CTRLTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if HAS_BLUETOOTH || HAS_BLE
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= T79c0ff0x00Tb4b4b4) Tb4b4b4{
Te6edf3bt_stopTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3bt_conf_saveTb4b4b4(Tff7b72falseTb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= T79c0ff0x01Tb4b4b4) Tb4b4b4{
Te6edf3bt_startTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3bt_conf_saveTb4b4b4(Tff7b72trueTb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= T79c0ff0x02Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3bt_state Tff7b72=Tff7b72= Te6edf3BT_STATE_OFFTb4b4b4) Tb4b4b4{
Te6edf3bt_startTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3bt_conf_saveTb4b4b4(Tff7b72trueTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3bt_state Tff7b72!Tff7b72= Te6edf3BT_STATE_CONNECTEDTb4b4b4) Tb4b4b4{
Te6edf3bt_enable_pairingTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_BT_UNPAIRTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if HAS_BLE
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= T79c0ff0x01Tb4b4b4) Tb4b4b4{ Te6edf3bt_debond_allTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_DISP_INTTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if HAS_DISPLAY
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3FESCTb4b4b4) Tb4b4b4{
Te6edf3ESCAPE Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3ESCAPETb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFENDTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FENDTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFESCTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FESCTb4b4b4;
Te6edf3ESCAPE Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Te6edf3display_intensity Tff7b72= Te6edf3sbyteTb4b4b4;
Te6edf3di_conf_saveTb4b4b4(Te6edf3display_intensityTb4b4b4)Tb4b4b4;
Te6edf3display_unblankTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_DISP_ADDRTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if HAS_DISPLAY
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3FESCTb4b4b4) Tb4b4b4{
Te6edf3ESCAPE Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3ESCAPETb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFENDTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FENDTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFESCTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FESCTb4b4b4;
Te6edf3ESCAPE Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Te6edf3display_addr Tff7b72= Te6edf3sbyteTb4b4b4;
Te6edf3da_conf_saveTb4b4b4(Te6edf3display_addrTb4b4b4)Tb4b4b4;
Tb4b4b4}

Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_DISP_BLNKTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if HAS_DISPLAY
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3FESCTb4b4b4) Tb4b4b4{
Te6edf3ESCAPE Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3ESCAPETb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFENDTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FENDTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFESCTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FESCTb4b4b4;
Te6edf3ESCAPE Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Te6edf3db_conf_saveTb4b4b4(Te6edf3sbyteTb4b4b4)Tb4b4b4;
Te6edf3display_unblankTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_DISP_ROTTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if HAS_DISPLAY
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3FESCTb4b4b4) Tb4b4b4{
Te6edf3ESCAPE Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3ESCAPETb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFENDTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FENDTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFESCTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FESCTb4b4b4;
Te6edf3ESCAPE Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Te6edf3drot_conf_saveTb4b4b4(Te6edf3sbyteTb4b4b4)Tb4b4b4;
Te6edf3display_unblankTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_DIS_IATb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3FESCTb4b4b4) Tb4b4b4{
Te6edf3ESCAPE Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3ESCAPETb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFENDTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FENDTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFESCTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FESCTb4b4b4;
Te6edf3ESCAPE Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Te6edf3dia_conf_saveTb4b4b4(Te6edf3sbyteTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_DISP_RCNDTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if HAS_DISPLAY
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3FESCTb4b4b4) Tb4b4b4{
Te6edf3ESCAPE Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3ESCAPETb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFENDTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FENDTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFESCTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FESCTb4b4b4;
Te6edf3ESCAPE Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72> T79c0ff0x00Tb4b4b4) Te6edf3recondition_display Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_NP_INTTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if HAS_NP
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3FESCTb4b4b4) Tb4b4b4{
Te6edf3ESCAPE Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3ESCAPETb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFENDTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FENDTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFESCTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FESCTb4b4b4;
Te6edf3ESCAPE Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Te6edf3sbyteTb4b4b4;
Te6edf3led_set_intensityTb4b4b4(Te6edf3sbyteTb4b4b4)Tb4b4b4;
Te6edf3np_int_conf_saveTb4b4b4(Te6edf3sbyteTb4b4b4)Tb4b4b4;
Tb4b4b4}

Tff7b72#Tff7b72endif
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}

Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32
Te6edf3portMUX_TYPE Te6edf3update_lock Tff7b72= Te6edf3portMUX_INITIALIZER_UNLOCKEDTb4b4b4;
Tff7b72#Tff7b72endif

Tff7b72bool Te6edf3medium_freeTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3update_modem_statusTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3avoid_interference Tff7b72&Tff7b72& Te6edf3interference_detectedTb4b4b4) Tb4b4b4{ Tff7b72return Tff7b72falseTb4b4b4; Tb4b4b4}
Tff7b72return Tff7b72!Te6edf3dcdTb4b4b4;
Tb4b4b4}

Tff7b72bool Te6edf3noise_floor_sampled Tff7b72= Tff7b72falseTb4b4b4;
Tff7b72int Te6edf3noise_floor_sample Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72int Te6edf3noise_floor_bufferTb4b4b4[Te6edf3NOISE_FLOOR_SAMPLESTb4b4b4] Tff7b72= Tb4b4b4{T79c0ff0Tb4b4b4}Tb4b4b4;
Tff7b72void Te6edf3update_noise_floorTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52 || MCU_VARIANT == MCU_NATIVE
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3dcdTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if HAS_LORA_LNA == false
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3noise_floor_sampled Tff7b72|Tff7b72| Te6edf3current_rssi Tff7b72< Te6edf3noise_floor Tff7b72+ Te6edf3CSMA_INFR_THRESHOLD_DBTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72else
Tff7b72if Tb4b4b4(Tb4b4b4(Tff7b72!Te6edf3noise_floor_sampled Tff7b72|Tff7b72| Te6edf3current_rssi Tff7b72< Te6edf3noise_floor Tff7b72+ Te6edf3CSMA_INFR_THRESHOLD_DBTb4b4b4) Tff7b72|Tff7b72| Tb4b4b4(Te6edf3noise_floor_sampled Tff7b72&Tff7b72& Tb4b4b4(Te6edf3noise_floor Tff7b72< Te6edf3LNA_GD_THRSHLD Tff7b72&Tff7b72& Te6edf3current_rssi Tff7b72<Tff7b72= Te6edf3LNA_GD_LIMITTb4b4b4)Tb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72if HAS_LORA_LNA
T8b949e// Discard invalid samples due to gain variance
T8b949e// during LoRa LNA re-calibration
Tff7b72if Tb4b4b4(Te6edf3current_rssi Tff7b72< Te6edf3noise_floorTff7b72-Te6edf3LORA_LNA_GVTTb4b4b4) Tb4b4b4{ Tff7b72returnTb4b4b4; Tb4b4b4}
Tff7b72#Tff7b72endif
Tff7b72bool Te6edf3sum_noise_floor Tff7b72= Tff7b72falseTb4b4b4;
Te6edf3noise_floor_bufferTb4b4b4[Te6edf3noise_floor_sampleTb4b4b4] Tff7b72= Te6edf3current_rssiTb4b4b4;
Te6edf3noise_floor_sample Tff7b72= Te6edf3noise_floor_sampleTff7b72+T79c0ff1Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3noise_floor_sample Tff7b72>Tff7b72= Te6edf3NOISE_FLOOR_SAMPLESTb4b4b4) Tb4b4b4{
Te6edf3noise_floor_sample Tff7b72%Tff7b72= Te6edf3NOISE_FLOOR_SAMPLESTb4b4b4;
Te6edf3noise_floor_sampled Tff7b72= Tff7b72trueTb4b4b4;
Te6edf3sum_noise_floor Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4}

Tff7b72if Tb4b4b4(Te6edf3noise_floor_sampled Tff7b72&Tff7b72& Te6edf3sum_noise_floorTb4b4b4) Tb4b4b4{
Te6edf3noise_floor Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72int Te6edf3ni Tff7b72= T79c0ff0Tb4b4b4; Te6edf3ni Tff7b72< Te6edf3NOISE_FLOOR_SAMPLESTb4b4b4; Te6edf3niTff7b72+Tff7b72+Tb4b4b4) Tb4b4b4{ Te6edf3noise_floor Tff7b72+Tff7b72= Te6edf3noise_floor_bufferTb4b4b4[Te6edf3niTb4b4b4]Tb4b4b4; Tb4b4b4}
Te6edf3noise_floor Tff7b72/Tff7b72= Te6edf3NOISE_FLOOR_SAMPLESTb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4}

Tff7b72#Tff7b72define LED_ID_TRIG 16
Tff7b72uint8_t Te6edf3led_id_filter Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72uint32_t Te6edf3interference_start Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72bool Te6edf3interference_persists Tff7b72= Tff7b72falseTb4b4b4;
Tff7b72void Te6edf3update_modem_statusTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32
Te6edf3portENTER_CRITICALTb4b4b4(Tff7b72&Te6edf3update_lockTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72elif MCU_VARIANT == MCU_NRF52
Te6edf3portENTER_CRITICALTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif

Tff7b72bool Te6edf3carrier_detected Tff7b72= Te6edf3LoRaTff7b72-Tff7b72>Te6edf3dcdTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3current_rssi Tff7b72= Te6edf3LoRaTff7b72-Tff7b72>Te6edf3currentRssiTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3last_status_update Tff7b72= Td2a8ffmillisTb4b4b4(Tb4b4b4)Tb4b4b4;

Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32
Te6edf3portEXIT_CRITICALTb4b4b4(Tff7b72&Te6edf3update_lockTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72elif MCU_VARIANT == MCU_NRF52
Te6edf3portEXIT_CRITICALTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif

Tff7b72#Tff7b72if HAS_LORA_LNA
Tff7b72if Tb4b4b4(Te6edf3noise_floor Tff7b72> Te6edf3LNA_GD_THRSHLDTb4b4b4) Tb4b4b4{ Te6edf3interference_detected Tff7b72= Tff7b72!Te6edf3carrier_detected Tff7b72&Tff7b72& Tb4b4b4(Te6edf3current_rssi Tff7b72> Tb4b4b4(Te6edf3noise_floorTff7b72+Te6edf3CSMA_INFR_THRESHOLD_DBTb4b4b4)Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72else Tb4b4b4{ Te6edf3interference_detected Tff7b72= Tff7b72!Te6edf3carrier_detected Tff7b72&Tff7b72& Tb4b4b4(Te6edf3current_rssi Tff7b72> Te6edf3LNA_GD_LIMITTb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72#Tff7b72else
Te6edf3interference_detected Tff7b72= Tff7b72!Te6edf3carrier_detected Tff7b72&Tff7b72& Tb4b4b4(Te6edf3current_rssi Tff7b72> Tb4b4b4(Te6edf3noise_floorTff7b72+Te6edf3CSMA_INFR_THRESHOLD_DBTb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif

Tff7b72if Tb4b4b4(Te6edf3interference_detectedTb4b4b4) Tb4b4b4{ Tff7b72if Tb4b4b4(Te6edf3led_id_filter Tff7b72< Te6edf3LED_ID_TRIGTb4b4b4) Tb4b4b4{ Te6edf3led_id_filter Tff7b72+Tff7b72= T79c0ff1Tb4b4b4; Tb4b4b4} Tb4b4b4}
Tff7b72else Tb4b4b4{ Tff7b72if Tb4b4b4(Te6edf3led_id_filter Tff7b72> T79c0ff0Tb4b4b4) Tb4b4b4{Te6edf3led_id_filter Tff7b72-Tff7b72= T79c0ff1Tb4b4b4; Tb4b4b4} Tb4b4b4}

T8b949e// Handle potential false interference detection due to
T8b949e// LNA recalibration, antenna swap, moving into new RF
T8b949e// environment or similar.
Tff7b72if Tb4b4b4(Te6edf3interference_detected Tff7b72&Tff7b72& Te6edf3current_rssi Tff7b72< Te6edf3CSMA_RFENV_RECAL_LIMIT_DBTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3interference_persistsTb4b4b4) Tb4b4b4{ Te6edf3interference_persists Tff7b72= Tff7b72trueTb4b4b4; Te6edf3interference_start Tff7b72= Td2a8ffmillisTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Td2a8ffmillisTb4b4b4(Tb4b4b4)Tff7b72-Te6edf3interference_start Tff7b72>Tff7b72= Te6edf3CSMA_RFENV_RECAL_MSTb4b4b4) Tb4b4b4{ Te6edf3noise_floor_sampled Tff7b72= Tff7b72falseTb4b4b4; Te6edf3interference_persists Tff7b72= Tff7b72falseTb4b4b4; Tb4b4b4}
Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{ Te6edf3interference_persists Tff7b72= Tff7b72falseTb4b4b4; Tb4b4b4}

Tff7b72if Tb4b4b4(Te6edf3carrier_detectedTb4b4b4) Tb4b4b4{ Te6edf3dcd Tff7b72= Tff7b72trueTb4b4b4; Tb4b4b4} Tff7b72else Tb4b4b4{ Te6edf3dcd Tff7b72= Tff7b72falseTb4b4b4; Tb4b4b4}

Te6edf3dcd_led Tff7b72= Te6edf3dcdTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3dcd_ledTb4b4b4) Tb4b4b4{ Te6edf3led_rx_onTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3interference_detected Tff7b72&Tff7b72& Te6edf3noise_floor_sampledTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3led_id_filter Tff7b72>Tff7b72= Te6edf3LED_ID_TRIGTb4b4b4) Tb4b4b4{ Te6edf3led_id_onTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3airtime_lockTb4b4b4) Tb4b4b4{ Te6edf3led_indicate_airtime_lockTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72else Tb4b4b4{ Te6edf3led_rx_offTb4b4b4(Tb4b4b4)Tb4b4b4; Te6edf3led_id_offTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4}
Tb4b4b4}

Te6edf3update_noise_floorTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}

Tff7b72void Te6edf3check_modem_statusTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Td2a8ffmillisTb4b4b4(Tb4b4b4)Tff7b72-Te6edf3last_status_update Tff7b72>Tff7b72= Te6edf3status_interval_msTb4b4b4) Tb4b4b4{
Te6edf3update_modem_statusTb4b4b4(Tb4b4b4)Tb4b4b4;

Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52 || MCU_VARIANT == MCU_NATIVE
Te6edf3util_samplesTb4b4b4[Te6edf3dcd_sampleTb4b4b4] Tff7b72= Te6edf3dcdTb4b4b4;
Te6edf3dcd_sample Tff7b72= Tb4b4b4(Te6edf3dcd_sampleTff7b72+T79c0ff1Tb4b4b4)Tff7b72%Te6edf3DCD_SAMPLESTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3dcd_sample Tff7b72% Te6edf3UTIL_UPDATE_INTERVAL Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{
Tff7b72int Te6edf3util_count Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72int Te6edf3ui Tff7b72= T79c0ff0Tb4b4b4; Te6edf3ui Tff7b72< Te6edf3DCD_SAMPLESTb4b4b4; Te6edf3uiTff7b72+Tff7b72+Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3util_samplesTb4b4b4[Te6edf3uiTb4b4b4]Tb4b4b4) Te6edf3util_countTff7b72+Tff7b72+Tb4b4b4;
Tb4b4b4}
Te6edf3local_channel_util Tff7b72= Tb4b4b4(Tff7b72floatTb4b4b4)Te6edf3util_count Tff7b72/ Tb4b4b4(Tff7b72floatTb4b4b4)Te6edf3DCD_SAMPLESTb4b4b4;
Te6edf3total_channel_util Tff7b72= Te6edf3local_channel_util Tff7b72+ Te6edf3airtimeTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3total_channel_util Tff7b72> T79c0ff1.0Tb4b4b4) Te6edf3total_channel_util Tff7b72= T79c0ff1.0Tb4b4b4;

Tff7b72int16_t Te6edf3cb Tff7b72= Te6edf3current_airtime_binTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72uint16_t Te6edf3nb Tff7b72= Te6edf3cbTff7b72+T79c0ff1Tb4b4b4; Tff7b72if Tb4b4b4(Te6edf3nb Tff7b72=Tff7b72= Te6edf3AIRTIME_BINSTb4b4b4) Tb4b4b4{ Te6edf3nb Tff7b72= T79c0ff0Tb4b4b4; Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3total_channel_util Tff7b72> Te6edf3longterm_binsTb4b4b4[Te6edf3cbTb4b4b4]Tb4b4b4) Te6edf3longterm_binsTb4b4b4[Te6edf3cbTb4b4b4] Tff7b72= Te6edf3total_channel_utilTb4b4b4;
Te6edf3longterm_binsTb4b4b4[Te6edf3nbTb4b4b4] Tff7b72= T79c0ff0.0Tb4b4b4;

Te6edf3update_airtimeTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4}
Tb4b4b4}

Tff7b72void Te6edf3validate_statusTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if MCU_VARIANT == MCU_1284P
Tff7b72uint8_t Te6edf3boot_flags Tff7b72= Te6edf3OPTIBOOT_MCUSRTb4b4b4;
Tff7b72uint8_t Te6edf3F_POR Tff7b72= Te6edf3PORFTb4b4b4;
Tff7b72uint8_t Te6edf3F_BOR Tff7b72= Te6edf3BORFTb4b4b4;
Tff7b72uint8_t Te6edf3F_WDR Tff7b72= Te6edf3WDRFTb4b4b4;
Tff7b72#Tff7b72elif MCU_VARIANT == MCU_2560
Tff7b72uint8_t Te6edf3boot_flags Tff7b72= Te6edf3OPTIBOOT_MCUSRTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3boot_flags Tff7b72=Tff7b72= T79c0ff0x00Tb4b4b4) Te6edf3boot_flags Tff7b72= T79c0ff0x03Tb4b4b4;
Tff7b72uint8_t Te6edf3F_POR Tff7b72= Te6edf3PORFTb4b4b4;
Tff7b72uint8_t Te6edf3F_BOR Tff7b72= Te6edf3BORFTb4b4b4;
Tff7b72uint8_t Te6edf3F_WDR Tff7b72= Te6edf3WDRFTb4b4b4;
Tff7b72#Tff7b72elif MCU_VARIANT == MCU_ESP32
T8b949e// TODO: Get ESP32 boot flags
Tff7b72uint8_t Te6edf3boot_flags Tff7b72= T79c0ff0x02Tb4b4b4;
Tff7b72uint8_t Te6edf3F_POR Tff7b72= T79c0ff0x00Tb4b4b4;
Tff7b72uint8_t Te6edf3F_BOR Tff7b72= T79c0ff0x00Tb4b4b4;
Tff7b72uint8_t Te6edf3F_WDR Tff7b72= T79c0ff0x01Tb4b4b4;
Tff7b72#Tff7b72elif MCU_VARIANT == MCU_NRF52
T8b949e// TODO: Get NRF52 boot flags
Tff7b72uint8_t Te6edf3boot_flags Tff7b72= T79c0ff0x02Tb4b4b4;
Tff7b72uint8_t Te6edf3F_POR Tff7b72= T79c0ff0x00Tb4b4b4;
Tff7b72uint8_t Te6edf3F_BOR Tff7b72= T79c0ff0x00Tb4b4b4;
Tff7b72uint8_t Te6edf3F_WDR Tff7b72= T79c0ff0x01Tb4b4b4;
Tff7b72#Tff7b72elif MCU_VARIANT == MCU_NATIVE
T8b949e// Native userspace daemon — no MCU reset cause registers. Report
T8b949e// a synthetic "power-on, bootloader path" status.
Tff7b72uint8_t Te6edf3boot_flags Tff7b72= T79c0ff0x02Tb4b4b4;
Tff7b72uint8_t Te6edf3F_POR Tff7b72= T79c0ff0x00Tb4b4b4;
Tff7b72uint8_t Te6edf3F_BOR Tff7b72= T79c0ff0x00Tb4b4b4;
Tff7b72uint8_t Te6edf3F_WDR Tff7b72= T79c0ff0x01Tb4b4b4;
Tff7b72#Tff7b72endif

Tff7b72if Tb4b4b4(Te6edf3hw_ready Tff7b72|Tff7b72| Te6edf3device_init_doneTb4b4b4) Tb4b4b4{
Te6edf3hw_ready Tff7b72= Tff7b72falseTb4b4b4;
Te6edf3printfTb4b4b4(Ta5d6ff"Ta5d6ff[init] Error, invalid hardware check stateTffea00\rTffea00\nTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72if HAS_DISPLAY
Tff7b72if Tb4b4b4(Te6edf3disp_readyTb4b4b4) Tb4b4b4{
Te6edf3device_init_done Tff7b72= Tff7b72trueTb4b4b4;
Te6edf3update_displayTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Te6edf3led_indicate_boot_errorTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}

Tff7b72if Tb4b4b4(Te6edf3boot_flags Tff7b72& Tb4b4b4(T79c0ff1Tff7b72<Tff7b72<Te6edf3F_PORTb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3boot_vector Tff7b72= Te6edf3START_FROM_POWERONTb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3boot_flags Tff7b72& Tb4b4b4(T79c0ff1Tff7b72<Tff7b72<Te6edf3F_BORTb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3boot_vector Tff7b72= Te6edf3START_FROM_BROWNOUTTb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3boot_flags Tff7b72& Tb4b4b4(T79c0ff1Tff7b72<Tff7b72<Te6edf3F_WDRTb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3boot_vector Tff7b72= Te6edf3START_FROM_BOOTLOADERTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Td2a8ffSerialTb4b4b4.Td2a8ffwriteTb4b4b4(Ta5d6ff"Ta5d6ffError, indeterminate boot vectorTffea00\rTffea00\nTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72if HAS_DISPLAY
Tff7b72if Tb4b4b4(Te6edf3disp_readyTb4b4b4) Tb4b4b4{
Te6edf3device_init_done Tff7b72= Tff7b72trueTb4b4b4;
Te6edf3update_displayTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Te6edf3led_indicate_boot_errorTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}

Tff7b72if Tb4b4b4(Te6edf3boot_vector Tff7b72=Tff7b72= Te6edf3START_FROM_BOOTLOADER Tff7b72|Tff7b72| Te6edf3boot_vector Tff7b72=Tff7b72= Te6edf3START_FROM_POWERONTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3eeprom_lock_setTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3eeprom_product_validTb4b4b4(Tb4b4b4) Tff7b72&Tff7b72& Te6edf3eeprom_model_validTb4b4b4(Tb4b4b4) Tff7b72&Tff7b72& Te6edf3eeprom_hwrev_validTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72ifdef DISABLE_FIRMWARE_CHECKSUM
T8b949e// Native builds self-provision the EEPROM in PinMap.cpp's
T8b949e// seed_eeprom_if_unprovisioned() but skip MD5 computation —
T8b949e// they short-circuit the checksum check here.
Tff7b72if Tb4b4b4(Tff7b72trueTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72else
Tff7b72if Tb4b4b4(Te6edf3eeprom_checksum_validTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72endif
Te6edf3eeprom_ok Tff7b72= Tff7b72trueTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3modem_installedTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if PLATFORM == PLATFORM_ESP32 || PLATFORM == PLATFORM_NRF52 || PLATFORM == PLATFORM_NATIVE
Tff7b72if Tb4b4b4(Te6edf3device_initTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3hw_ready Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3hw_ready Tff7b72= Tff7b72falseTb4b4b4;
Te6edf3printfTb4b4b4(Ta5d6ff"Ta5d6ff[init] Error, device init failedTffea00\rTffea00\nTa5d6ff"Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72else
Te6edf3hw_ready Tff7b72= Tff7b72trueTb4b4b4;
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3hw_ready Tff7b72= Tff7b72falseTb4b4b4;
Te6edf3printfTb4b4b4(Ta5d6ff"Ta5d6ff[init] No radio module foundTffea00\rTffea00\nTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72if HAS_DISPLAY
Tff7b72if Tb4b4b4(Te6edf3disp_readyTb4b4b4) Tb4b4b4{
Te6edf3device_init_done Tff7b72= Tff7b72trueTb4b4b4;
Te6edf3update_displayTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3hw_ready Tff7b72&Tff7b72& Te6edf3eeprom_have_confTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3eeprom_conf_loadTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3op_mode Tff7b72= Te6edf3MODE_TNCTb4b4b4;
Te6edf3startRadioTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3hw_ready Tff7b72= Tff7b72falseTb4b4b4;
Te6edf3printfTb4b4b4(Ta5d6ff"Ta5d6ff[init] Invalid EEPROM checksumTffea00\rTffea00\nTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72if HAS_DISPLAY
Tff7b72if Tb4b4b4(Te6edf3disp_readyTb4b4b4) Tb4b4b4{
Te6edf3device_init_done Tff7b72= Tff7b72trueTb4b4b4;
Te6edf3update_displayTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3hw_ready Tff7b72= Tff7b72falseTb4b4b4;
Te6edf3printfTb4b4b4(Ta5d6ff"Ta5d6ff[init] Invalid EEPROM configurationTffea00\rTffea00\nTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72if HAS_DISPLAY
Tff7b72if Tb4b4b4(Te6edf3disp_readyTb4b4b4) Tb4b4b4{
Te6edf3device_init_done Tff7b72= Tff7b72trueTb4b4b4;
Te6edf3update_displayTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3hw_ready Tff7b72= Tff7b72falseTb4b4b4;
Te6edf3printfTb4b4b4(Ta5d6ff"Ta5d6ff[init] Device unprovisioned, no device configuration found in EEPROMTffea00\rTffea00\nTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72if HAS_DISPLAY
Tff7b72if Tb4b4b4(Te6edf3disp_readyTb4b4b4) Tb4b4b4{
Te6edf3device_init_done Tff7b72= Tff7b72trueTb4b4b4;
Te6edf3update_displayTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3hw_ready Tff7b72= Tff7b72falseTb4b4b4;
Te6edf3printfTb4b4b4(Ta5d6ff"Ta5d6ff[init] Error, incorrect boot vectorTffea00\rTffea00\nTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72if HAS_DISPLAY
Tff7b72if Tb4b4b4(Te6edf3disp_readyTb4b4b4) Tb4b4b4{
Te6edf3device_init_done Tff7b72= Tff7b72trueTb4b4b4;
Te6edf3update_displayTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Te6edf3led_indicate_boot_errorTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}

Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52 || MCU_VARIANT == MCU_NATIVE
Tff7b72void Te6edf3update_csma_parametersTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72int Te6edf3airtime_pct Tff7b72= Tb4b4b4(Tff7b72intTb4b4b4)Tb4b4b4(Te6edf3airtimeTff7b72*T79c0ff100Tb4b4b4)Tb4b4b4;
Tff7b72int Te6edf3new_cw_band Tff7b72= Te6edf3cw_bandTb4b4b4;

Tff7b72if Tb4b4b4(Te6edf3airtime_pct Tff7b72<Tff7b72= Te6edf3CSMA_BAND_1_MAX_AIRTIMETb4b4b4) Tb4b4b4{ Te6edf3new_cw_band Tff7b72= T79c0ff1Tb4b4b4; Tb4b4b4}
Tff7b72else Tb4b4b4{
Tff7b72int Te6edf3at Tff7b72= Te6edf3airtime_pct Tff7b72+ Te6edf3CSMA_BAND_1_MAX_AIRTIMETb4b4b4;
Te6edf3new_cw_band Tff7b72= Td2a8ffmapTb4b4b4(Te6edf3atTb4b4b4, Te6edf3CSMA_BAND_1_MAX_AIRTIMETb4b4b4, Te6edf3CSMA_BAND_N_MIN_AIRTIMETb4b4b4, T79c0ff2Tb4b4b4, Te6edf3CSMA_CW_BANDSTb4b4b4)Tb4b4b4;
Tb4b4b4}

Tff7b72if Tb4b4b4(Te6edf3new_cw_band Tff7b72> Te6edf3CSMA_CW_BANDSTb4b4b4) Tb4b4b4{ Te6edf3new_cw_band Tff7b72= Te6edf3CSMA_CW_BANDSTb4b4b4; Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3new_cw_band Tff7b72!Tff7b72= Te6edf3cw_bandTb4b4b4) Tb4b4b4{
Te6edf3cw_band Tff7b72= Tb4b4b4(Tff7b72uint8_tTb4b4b4)Tb4b4b4(Te6edf3new_cw_bandTb4b4b4)Tb4b4b4;
Te6edf3cw_min Tff7b72= Tb4b4b4(Te6edf3cw_bandT79c0ff-1Tb4b4b4) Tff7b72* Te6edf3CSMA_CW_PER_BAND_WINDOWSTb4b4b4;
Te6edf3cw_max Tff7b72= Tb4b4b4(Te6edf3cw_bandTb4b4b4) Tff7b72* Te6edf3CSMA_CW_PER_BAND_WINDOWS Tff7b72- T79c0ff1Tb4b4b4;
Te6edf3kiss_indicate_csma_statsTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72#Tff7b72endif

Tff7b72void Te6edf3tx_queue_handlerTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3airtime_lock Tff7b72&Tff7b72& Te6edf3queue_height Tff7b72> T79c0ff0Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3csma_cw Tff7b72=Tff7b72= T79c0ff-1Tb4b4b4) Tb4b4b4{
Te6edf3csma_cw Tff7b72= Td2a8ffrandomTb4b4b4(Te6edf3cw_minTb4b4b4, Te6edf3cw_maxTb4b4b4)Tb4b4b4;
Te6edf3cw_wait_target Tff7b72= Te6edf3csma_cw Tff7b72* Te6edf3csma_slot_msTb4b4b4;
Tb4b4b4}

Tff7b72if Tb4b4b4(Te6edf3difs_wait_start Tff7b72=Tff7b72= T79c0ff-1Tb4b4b4) Tb4b4b4{ T8b949e// DIFS wait not yet started
Tff7b72if Tb4b4b4(Te6edf3medium_freeTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{ Te6edf3difs_wait_start Tff7b72= Td2a8ffmillisTb4b4b4(Tb4b4b4)Tb4b4b4; Tff7b72returnTb4b4b4; Tb4b4b4} T8b949e// Set DIFS wait start time
Tff7b72else Tb4b4b4{ Tff7b72returnTb4b4b4; Tb4b4b4} Tb4b4b4} T8b949e// Medium not yet free, continue waiting
Tff7b72else Tb4b4b4{ T8b949e// We are waiting for DIFS or CW to pass
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3medium_freeTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{ Te6edf3difs_wait_start Tff7b72= T79c0ff-1Tb4b4b4; Te6edf3cw_wait_start Tff7b72= T79c0ff-1Tb4b4b4; Tff7b72returnTb4b4b4; Tb4b4b4} T8b949e// Medium became occupied while in DIFS wait, restart waiting when free again
Tff7b72else Tb4b4b4{ T8b949e// Medium is free, so continue waiting
Tff7b72if Tb4b4b4(Td2a8ffmillisTb4b4b4(Tb4b4b4) Tff7b72< Te6edf3difs_wait_startTff7b72+Te6edf3difs_msTb4b4b4) Tb4b4b4{ Tff7b72returnTb4b4b4; Tb4b4b4} T8b949e// DIFS has not yet passed, continue waiting
Tff7b72else Tb4b4b4{ T8b949e// DIFS has passed, and we are now in CW wait
Tff7b72if Tb4b4b4(Te6edf3cw_wait_start Tff7b72=Tff7b72= T79c0ff-1Tb4b4b4) Tb4b4b4{ Te6edf3cw_wait_start Tff7b72= Td2a8ffmillisTb4b4b4(Tb4b4b4)Tb4b4b4; Tff7b72returnTb4b4b4; Tb4b4b4} T8b949e// If we haven't started counting CW wait time, do it from now
Tff7b72else Tb4b4b4{ T8b949e// If we are already counting CW wait time, add it to the counter
Te6edf3cw_wait_passed Tff7b72+Tff7b72= Td2a8ffmillisTb4b4b4(Tb4b4b4)Tff7b72-Te6edf3cw_wait_startTb4b4b4; Te6edf3cw_wait_start Tff7b72= Td2a8ffmillisTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3cw_wait_passed Tff7b72< Te6edf3cw_wait_targetTb4b4b4) Tb4b4b4{ Tff7b72returnTb4b4b4; Tb4b4b4} T8b949e// Contention window wait time has not yet passed, continue waiting
Tff7b72else Tb4b4b4{ T8b949e// Wait time has passed, flush the queue
Tff7b72bool Te6edf3should_flush Tff7b72= Tff7b72!Te6edf3lora_limit_rate Tff7b72&Tff7b72& Tff7b72!Te6edf3lora_guard_rateTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3should_flushTb4b4b4) Tb4b4b4{ Te6edf3flush_queueTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4} Tff7b72else Tb4b4b4{ Te6edf3pop_queueTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4}
Te6edf3cw_wait_passed Tff7b72= T79c0ff0Tb4b4b4; Te6edf3csma_cw Tff7b72= T79c0ff-1Tb4b4b4; Te6edf3difs_wait_start Tff7b72= T79c0ff-1Tb4b4b4; Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}

Tff7b72void Te6edf3work_while_waitingTb4b4b4(Tb4b4b4) Tb4b4b4{ Tffa657loopTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4}

Tff7b72void Tffa657loopTb4b4b4(Tb4b4b4) Tb4b4b4{

Tff7b72#Tff7b72if MCU_VARIANT == MCU_NATIVE
T8b949e// Deferred-reboot hook: a KISS-driven property change or CMD_RESET in
T8b949e// a prior iteration called hard_reset() → native_request_reboot(), which
T8b949e// just set a flag. By the time we re-enter loop(), any KISS ACK from
T8b949e// that handler has already been written to the socket. Now perform the
T8b949e// cleanup + re-exec. native_reboot::perform() is [[noreturn]].
Tff7b72extern Tff7b72bool Te6edf3native_reboot_pendingTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72extern Tff7b72void Te6edf3native_reboot_performTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3native_reboot_pendingTb4b4b4(Tb4b4b4)Tb4b4b4) Te6edf3native_reboot_performTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif

Tff7b72#Tff7b72ifdef HAS_RNS
T8b949e// CBA
Tff7b72if Tb4b4b4(Te6edf3reticulumTb4b4b4) Tb4b4b4{
Tff7b72try Tb4b4b4{
Te6edf3reticulumTb4b4b4.Tffa657loopTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72catch Tb4b4b4(Tff7b72const Te6edf3stdTff7b72:Tff7b72:Te6edf3bad_allocTff7b72&Tb4b4b4) Tb4b4b4{
Te6edf3ERRORTb4b4b4(Ta5d6ff"Ta5d6ffRNS loop failed: bad_alloc - out of memoryTa5d6ff"Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72catch Tb4b4b4(Te6edf3stdTff7b72:Tff7b72:Te6edf3exceptionTff7b72& Te6edf3eTb4b4b4) Tb4b4b4{
Te6edf3ERRORFTb4b4b4(Ta5d6ff"Ta5d6ffRNS loop failed: %sTa5d6ff"Tb4b4b4, Te6edf3eTb4b4b4.Te6edf3whatTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72#Tff7b72endif

Tff7b72if Tb4b4b4(Te6edf3radio_onlineTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NATIVE
Te6edf3LoRaTff7b72-Tff7b72>Te6edf3handleDio0IfPendingTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3modem_packet_t Tff7b72*Te6edf3modem_packet Tff7b72= Tffa657NULLTb4b4b4;
Tff7b72ifTb4b4b4(Te6edf3modem_packet_queue Tff7b72&Tff7b72& Te6edf3xQueueReceiveTb4b4b4(Te6edf3modem_packet_queueTb4b4b4, Tff7b72&Te6edf3modem_packetTb4b4b4, T79c0ff0Tb4b4b4) Tff7b72=Tff7b72= Te6edf3pdTRUE Tff7b72&Tff7b72& Te6edf3modem_packetTb4b4b4) Tb4b4b4{
Te6edf3host_write_len Tff7b72= Te6edf3modem_packetTff7b72-Tff7b72>Te6edf3lenTb4b4b4;
Te6edf3last_rssi Tff7b72= Te6edf3modem_packetTff7b72-Tff7b72>Te6edf3rssiTb4b4b4;
Te6edf3last_snr_raw Tff7b72= Te6edf3modem_packetTff7b72-Tff7b72>Te6edf3snr_rawTb4b4b4;
Te6edf3memcpyTb4b4b4(Tff7b72&Te6edf3pbufTb4b4b4, Te6edf3modem_packetTff7b72-Tff7b72>Te6edf3dataTb4b4b4, Te6edf3modem_packetTff7b72-Tff7b72>Te6edf3lenTb4b4b4)Tb4b4b4;
Te6edf3freeTb4b4b4(Te6edf3modem_packetTb4b4b4)Tb4b4b4;
Te6edf3modem_packet Tff7b72= Tffa657NULLTb4b4b4;

Te6edf3kiss_indicate_stat_rssiTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3kiss_indicate_stat_snrTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3kiss_write_packetTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}

Te6edf3airtime_lock Tff7b72= Tff7b72falseTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3st_airtime_limit Tff7b72!Tff7b72= T79c0ff0.0 Tff7b72&Tff7b72& Te6edf3airtime Tff7b72>Tff7b72= Te6edf3st_airtime_limitTb4b4b4) Te6edf3airtime_lock Tff7b72= Tff7b72trueTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3lt_airtime_limit Tff7b72!Tff7b72= T79c0ff0.0 Tff7b72&Tff7b72& Te6edf3longterm_airtime Tff7b72>Tff7b72= Te6edf3lt_airtime_limitTb4b4b4) Te6edf3airtime_lock Tff7b72= Tff7b72trueTb4b4b4;

Tff7b72#Tff7b72elif MCU_VARIANT == MCU_NRF52
Te6edf3LoRaTff7b72-Tff7b72>Te6edf3handleDio0IfPendingTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3modem_packet_t Tff7b72*Te6edf3modem_packet Tff7b72= Tffa657NULLTb4b4b4;
Tff7b72ifTb4b4b4(Te6edf3modem_packet_queue Tff7b72&Tff7b72& Te6edf3xQueueReceiveTb4b4b4(Te6edf3modem_packet_queueTb4b4b4, Tff7b72&Te6edf3modem_packetTb4b4b4, T79c0ff0Tb4b4b4) Tff7b72=Tff7b72= Te6edf3pdTRUE Tff7b72&Tff7b72& Te6edf3modem_packetTb4b4b4) Tb4b4b4{
Te6edf3memcpyTb4b4b4(Tff7b72&Te6edf3pbufTb4b4b4, Te6edf3modem_packetTff7b72-Tff7b72>Te6edf3dataTb4b4b4, Te6edf3modem_packetTff7b72-Tff7b72>Te6edf3lenTb4b4b4)Tb4b4b4;
Te6edf3host_write_len Tff7b72= Te6edf3modem_packetTff7b72-Tff7b72>Te6edf3lenTb4b4b4;
Te6edf3freeTb4b4b4(Te6edf3modem_packetTb4b4b4)Tb4b4b4;
Te6edf3modem_packet Tff7b72= Tffa657NULLTb4b4b4;

Te6edf3portENTER_CRITICALTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3last_rssi Tff7b72= Te6edf3LoRaTff7b72-Tff7b72>Te6edf3packetRssiTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3last_snr_raw Tff7b72= Te6edf3LoRaTff7b72-Tff7b72>Te6edf3packetSnrRawTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3portEXIT_CRITICALTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3kiss_indicate_stat_rssiTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3kiss_indicate_stat_snrTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3kiss_write_packetTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}

Te6edf3airtime_lock Tff7b72= Tff7b72falseTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3st_airtime_limit Tff7b72!Tff7b72= T79c0ff0.0 Tff7b72&Tff7b72& Te6edf3airtime Tff7b72>Tff7b72= Te6edf3st_airtime_limitTb4b4b4) Te6edf3airtime_lock Tff7b72= Tff7b72trueTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3lt_airtime_limit Tff7b72!Tff7b72= T79c0ff0.0 Tff7b72&Tff7b72& Te6edf3longterm_airtime Tff7b72>Tff7b72= Te6edf3lt_airtime_limitTb4b4b4) Te6edf3airtime_lock Tff7b72= Tff7b72trueTb4b4b4;

Tff7b72#Tff7b72endif

Te6edf3tx_queue_handlerTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3check_modem_statusTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72if MCU_VARIANT == MCU_NATIVE
T8b949e// Drop a TCP host client that's gone silent past the idle window.
T8b949e// poll_accept() in buffer_serial() handles the connect side; this
T8b949e// is the disconnect-side sweep.
Te6edf3native_kiss_tcpTff7b72:Tff7b72:Te6edf3check_activeTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif

Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3hw_readyTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3console_activeTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if HAS_CONSOLE
Te6edf3console_loopTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3led_indicate_standbyTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{

Te6edf3led_indicate_not_readyTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3stopRadioTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}

Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52 || MCU_VARIANT == MCU_NATIVE
Te6edf3buffer_serialTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3fifo_isemptyTb4b4b4(Tff7b72&Te6edf3serialFIFOTb4b4b4)Tb4b4b4) Te6edf3serial_pollTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72else
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3fifo_isempty_lockedTb4b4b4(Tff7b72&Te6edf3serialFIFOTb4b4b4)Tb4b4b4) Te6edf3serial_pollTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif

Tff7b72#Tff7b72if defined(ENABLE_WEBSOCKETS) && __has_include(<WiFi.h>)
Te6edf3ws_consoleTff7b72:Tff7b72:Te6edf3serviceTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif

Tff7b72#Tff7b72if HAS_DISPLAY
Tff7b72if Tb4b4b4(Te6edf3disp_ready Tff7b72&Tff7b72& Tff7b72!Te6edf3display_updatingTb4b4b4) Te6edf3update_displayTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif

Tff7b72#Tff7b72if HAS_PMU
Tff7b72if Tb4b4b4(Te6edf3pmu_readyTb4b4b4) Te6edf3update_pmuTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif

Tff7b72#Tff7b72if HAS_BLUETOOTH || HAS_BLE == true
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3console_active Tff7b72&Tff7b72& Te6edf3bt_readyTb4b4b4) Te6edf3update_btTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif

Tff7b72#Tff7b72if HAS_WIFI
Tff7b72if Tb4b4b4(Te6edf3wifi_initializedTb4b4b4) Te6edf3update_wifiTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif

Tff7b72#Tff7b72if HAS_INPUT
Te6edf3input_readTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif

T8b949e// Feed WDT
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32
Te6edf3esp_task_wdt_resetTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72elif MCU_VARIANT == MCU_NRF52
Te6edf3NRF_WDTTff7b72-Tff7b72>Te6edf3RRTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72= Te6edf3WDT_RR_RR_ReloadTb4b4b4;
Tff7b72#Tff7b72endif

Tff7b72if Tb4b4b4(Te6edf3memory_lowTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if PLATFORM == PLATFORM_ESP32
Tff7b72if Tb4b4b4(Te6edf3esp_get_free_heap_sizeTb4b4b4(Tb4b4b4) Tff7b72< T79c0ff8192Tb4b4b4) Tb4b4b4{
Te6edf3kiss_indicate_errorTb4b4b4(Te6edf3ERROR_MEMORY_LOWTb4b4b4)Tb4b4b4; Te6edf3memory_low Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3memory_low Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72else
Te6edf3kiss_indicate_errorTb4b4b4(Te6edf3ERROR_MEMORY_LOWTb4b4b4)Tb4b4b4; Te6edf3memory_low Tff7b72= Tff7b72falseTb4b4b4;
Tff7b72#Tff7b72endif
Tb4b4b4}
Tb4b4b4}

Tff7b72void Te6edf3sleep_nowTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if HAS_SLEEP == true
Te6edf3stopRadioTb4b4b4(Tb4b4b4)Tb4b4b4; T8b949e// TODO: Check this on all platforms
Tff7b72#Tff7b72if PLATFORM == PLATFORM_ESP32
Tff7b72#Tff7b72if BOARD_MODEL == BOARD_T3S3 || BOARD_MODEL == BOARD_XIAO_S3
Tff7b72#Tff7b72if HAS_DISPLAY
Te6edf3display_intensity Tff7b72= T79c0ff0Tb4b4b4;
Te6edf3update_displayTb4b4b4(Tff7b72trueTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72if BOARD_MODEL == BOARD_HELTEC32_V4
Td2a8ffdigitalWriteTb4b4b4(Te6edf3LORA_PA_CPSTb4b4b4, Tff7b72LOWTb4b4b4)Tb4b4b4;
Td2a8ffdigitalWriteTb4b4b4(Te6edf3LORA_PA_CSDTb4b4b4, Tff7b72LOWTb4b4b4)Tb4b4b4;
Td2a8ffdigitalWriteTb4b4b4(Te6edf3LORA_PA_PWR_ENTb4b4b4, Tff7b72LOWTb4b4b4)Tb4b4b4;
Td2a8ffdigitalWriteTb4b4b4(Te6edf3VextTb4b4b4, Tff7b72HIGHTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72if BOARD_MODEL == BOARD_HELTEC_TRACKER_V2
Td2a8ffdigitalWriteTb4b4b4(Te6edf3LORA_PA_CTXTb4b4b4, Tff7b72LOWTb4b4b4)Tb4b4b4;
Td2a8ffdigitalWriteTb4b4b4(Te6edf3LORA_PA_CSDTb4b4b4, Tff7b72LOWTb4b4b4)Tb4b4b4;
Td2a8ffdigitalWriteTb4b4b4(Te6edf3LORA_PA_PWR_ENTb4b4b4, Tff7b72LOWTb4b4b4)Tb4b4b4;
Td2a8ffdigitalWriteTb4b4b4(Te6edf3VextTb4b4b4, Te6edf3VEXT_OFFTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72if PIN_DISP_SLEEP >= 0
Td2a8ffpinModeTb4b4b4(Te6edf3PIN_DISP_SLEEPTb4b4b4, Tff7b72OUTPUTTb4b4b4)Tb4b4b4;
Td2a8ffdigitalWriteTb4b4b4(Te6edf3PIN_DISP_SLEEPTb4b4b4, Te6edf3DISP_SLEEP_LEVELTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72if HAS_BLUETOOTH
Tff7b72if Tb4b4b4(Te6edf3bt_state Tff7b72=Tff7b72= Te6edf3BT_STATE_CONNECTEDTb4b4b4) Tb4b4b4{
Te6edf3bt_stopTb4b4b4(Tb4b4b4)Tb4b4b4;
Td2a8ffdelayTb4b4b4(T79c0ff100Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Te6edf3esp_sleep_enable_ext0_wakeupTb4b4b4(Te6edf3PIN_WAKEUPTb4b4b4, Te6edf3WAKEUP_LEVELTb4b4b4)Tb4b4b4;
Te6edf3esp_deep_sleep_startTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72elif PLATFORM == PLATFORM_NRF52
Tff7b72#Tff7b72if BOARD_MODEL == BOARD_HELTEC_T114
Te6edf3npsetTb4b4b4(T79c0ff0Tb4b4b4,T79c0ff0Tb4b4b4,T79c0ff0Tb4b4b4)Tb4b4b4;
Td2a8ffdigitalWriteTb4b4b4(Te6edf3PIN_VEXT_ENTb4b4b4, Tff7b72LOWTb4b4b4)Tb4b4b4;
Td2a8ffdigitalWriteTb4b4b4(Te6edf3PIN_T114_TFT_BLGTTb4b4b4, Tff7b72HIGHTb4b4b4)Tb4b4b4;
Td2a8ffdigitalWriteTb4b4b4(Te6edf3PIN_T114_TFT_ENTb4b4b4, Tff7b72HIGHTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72elif BOARD_MODEL == BOARD_TECHO
Tff7b72for Tb4b4b4(Tff7b72uint8_t Te6edf3i Tff7b72= Te6edf3display_intensityTb4b4b4; Te6edf3i Tff7b72> T79c0ff0Tb4b4b4; Te6edf3iTff7b72-Tff7b72-Tb4b4b4) Tb4b4b4{ Td2a8ffanalogWriteTb4b4b4(Te6edf3pin_backlightTb4b4b4, Te6edf3iT79c0ff-1Tb4b4b4)Tb4b4b4; Td2a8ffdelayTb4b4b4(T79c0ff1Tb4b4b4)Tb4b4b4; Tb4b4b4}
Te6edf3epd_blackTb4b4b4(Tff7b72trueTb4b4b4)Tb4b4b4; Td2a8ffdelayTb4b4b4(T79c0ff300Tb4b4b4)Tb4b4b4; Te6edf3epd_blackTb4b4b4(Tff7b72trueTb4b4b4)Tb4b4b4; Td2a8ffdelayTb4b4b4(T79c0ff300Tb4b4b4)Tb4b4b4; Te6edf3epd_blackTb4b4b4(Tff7b72falseTb4b4b4)Tb4b4b4;
Td2a8ffdelayTb4b4b4(T79c0ff2000Tb4b4b4)Tb4b4b4;
Td2a8ffanalogWriteTb4b4b4(Te6edf3PIN_VEXT_ENTb4b4b4, T79c0ff0Tb4b4b4)Tb4b4b4;
Td2a8ffdelayTb4b4b4(T79c0ff100Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Te6edf3sd_power_gpregret_setTb4b4b4(T79c0ff0Tb4b4b4, T79c0ff0x6dTb4b4b4)Tb4b4b4;
Te6edf3nrf_gpio_cfg_sense_inputTb4b4b4(Te6edf3pin_btn_usr1Tb4b4b4, Te6edf3NRF_GPIO_PIN_PULLUPTb4b4b4, Te6edf3NRF_GPIO_PIN_SENSE_LOWTb4b4b4)Tb4b4b4;
Te6edf3NRF_POWERTff7b72-Tff7b72>Te6edf3SYSTEMOFF Tff7b72= T79c0ff1Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72endif
Tb4b4b4}

Tff7b72void Te6edf3button_eventTb4b4b4(Tff7b72uint8_t Te6edf3eventTb4b4b4, Tff7b72unsigned Tff7b72long Te6edf3durationTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52 || MCU_VARIANT == MCU_NATIVE
Tff7b72if Tb4b4b4(Te6edf3display_blankedTb4b4b4) Tb4b4b4{
Te6edf3display_unblankTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3duration Tff7b72> T79c0ff10000Tb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if HAS_CONSOLE
Tff7b72#Tff7b72if HAS_BLUETOOTH || HAS_BLE
Te6edf3bt_stopTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Te6edf3console_active Tff7b72= Tff7b72trueTb4b4b4;
Te6edf3console_startTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3duration Tff7b72> T79c0ff5000Tb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if HAS_BLUETOOTH || HAS_BLE
Tff7b72if Tb4b4b4(Te6edf3bt_state Tff7b72!Tff7b72= Te6edf3BT_STATE_CONNECTEDTb4b4b4) Tb4b4b4{ Te6edf3bt_enable_pairingTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3duration Tff7b72> T79c0ff700Tb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if HAS_SLEEP
Te6edf3sleep_nowTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72#Tff7b72if HAS_BLUETOOTH || HAS_BLE
Tff7b72if Tb4b4b4(Te6edf3bt_state Tff7b72!Tff7b72= Te6edf3BT_STATE_CONNECTEDTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3bt_state Tff7b72=Tff7b72= Te6edf3BT_STATE_OFFTb4b4b4) Tb4b4b4{
Te6edf3bt_startTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3bt_conf_saveTb4b4b4(Tff7b72trueTb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3bt_stopTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3bt_conf_saveTb4b4b4(Tff7b72falseTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4}
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4}

Tff7b72volatile Tff7b72bool Te6edf3serial_polling Tff7b72= Tff7b72falseTb4b4b4;
Tff7b72void Te6edf3serial_pollTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3serial_polling Tff7b72= Tff7b72trueTb4b4b4;

Tff7b72#Tff7b72if MCU_VARIANT != MCU_ESP32 && MCU_VARIANT != MCU_NRF52 && MCU_VARIANT != MCU_NATIVE
Tff7b72while Tb4b4b4(Tff7b72!Te6edf3fifo_isempty_lockedTb4b4b4(Tff7b72&Te6edf3serialFIFOTb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72else
Tff7b72while Tb4b4b4(Tff7b72!Te6edf3fifo_isemptyTb4b4b4(Tff7b72&Te6edf3serialFIFOTb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72endif
Tff7b72char Te6edf3sbyte Tff7b72= Te6edf3fifo_popTb4b4b4(Tff7b72&Te6edf3serialFIFOTb4b4b4)Tb4b4b4;
Te6edf3serial_callbackTb4b4b4(Te6edf3sbyteTb4b4b4)Tb4b4b4;
Tb4b4b4}

Te6edf3serial_polling Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}

Tff7b72#Tff7b72if MCU_VARIANT != MCU_ESP32
Tff7b72#Tff7b72define MAX_CYCLES 20
Tff7b72#Tff7b72else
Tff7b72#Tff7b72define MAX_CYCLES 10
Tff7b72#Tff7b72endif
Tff7b72void Te6edf3buffer_serialTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3serial_bufferingTb4b4b4) Tb4b4b4{
Te6edf3serial_buffering Tff7b72= Tff7b72trueTb4b4b4;

Tff7b72uint8_t Te6edf3c Tff7b72= T79c0ff0Tb4b4b4;

Tff7b72#Tff7b72if MCU_VARIANT == MCU_NATIVE
T8b949e// Refill the TCP staging buffer once per buffer_serial() pass —
T8b949e// accept any pending connection (or reject if we're already busy),
T8b949e// then drain whatever the kernel queued for the active client.
Te6edf3native_kiss_tcpTff7b72:Tff7b72:Te6edf3poll_acceptTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72while Tb4b4b4(Te6edf3c Tff7b72< Te6edf3MAX_CYCLES Tff7b72&Tff7b72& Te6edf3native_kiss_tcpTff7b72:Tff7b72:Td2a8ffavailableTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3cTff7b72+Tff7b72+Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3fifo_isfullTb4b4b4(Tff7b72&Te6edf3serialFIFOTb4b4b4)Tb4b4b4) Tb4b4b4{ Te6edf3fifo_pushTb4b4b4(Tff7b72&Te6edf3serialFIFOTb4b4b4, Te6edf3native_kiss_tcpTff7b72:Tff7b72:Td2a8ffreadTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4}
Tff7b72#Tff7b72else
Tff7b72#Tff7b72if HAS_BLUETOOTH || HAS_BLE == true
Tff7b72while Tb4b4b4(
Te6edf3c Tff7b72< Te6edf3MAX_CYCLES Tff7b72&Tff7b72&
Tff7b72#Tff7b72if HAS_WIFI
Tb4b4b4( Tb4b4b4(Te6edf3bt_state Tff7b72!Tff7b72= Te6edf3BT_STATE_CONNECTED Tff7b72&Tff7b72& Td2a8ffSerialTb4b4b4.Td2a8ffavailableTb4b4b4(Tb4b4b4)Tb4b4b4) Tff7b72|Tff7b72| Tb4b4b4(Te6edf3bt_state Tff7b72=Tff7b72= Te6edf3BT_STATE_CONNECTED Tff7b72&Tff7b72& Te6edf3SerialBTTb4b4b4.Td2a8ffavailableTb4b4b4(Tb4b4b4)Tb4b4b4) Tff7b72|Tff7b72| Tb4b4b4(Te6edf3wr_state Tff7b72>Tff7b72= Te6edf3WR_STATE_ON Tff7b72&Tff7b72& Te6edf3wifi_remote_availableTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4)
Tff7b72#Tff7b72else
Tb4b4b4( Tb4b4b4(Te6edf3bt_state Tff7b72!Tff7b72= Te6edf3BT_STATE_CONNECTED Tff7b72&Tff7b72& Td2a8ffSerialTb4b4b4.Td2a8ffavailableTb4b4b4(Tb4b4b4)Tb4b4b4) Tff7b72|Tff7b72| Tb4b4b4(Te6edf3bt_state Tff7b72=Tff7b72= Te6edf3BT_STATE_CONNECTED Tff7b72&Tff7b72& Te6edf3SerialBTTb4b4b4.Td2a8ffavailableTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4)
Tff7b72#Tff7b72endif
Tb4b4b4)
Tff7b72#Tff7b72else
Tff7b72while Tb4b4b4(Te6edf3c Tff7b72< Te6edf3MAX_CYCLES Tff7b72&Tff7b72& Td2a8ffSerialTb4b4b4.Td2a8ffavailableTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72#Tff7b72endif
Tb4b4b4{
Te6edf3cTff7b72+Tff7b72+Tb4b4b4;

Tff7b72#Tff7b72if MCU_VARIANT != MCU_ESP32 && MCU_VARIANT != MCU_NRF52
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3fifo_isfull_lockedTb4b4b4(Tff7b72&Te6edf3serialFIFOTb4b4b4)Tb4b4b4) Tb4b4b4{ Te6edf3fifo_push_lockedTb4b4b4(Tff7b72&Te6edf3serialFIFOTb4b4b4, Td2a8ffSerialTb4b4b4.Td2a8ffreadTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72#Tff7b72elif HAS_BLUETOOTH || HAS_BLE == true || HAS_WIFI
Tff7b72if Tb4b4b4(Te6edf3bt_state Tff7b72=Tff7b72= Te6edf3BT_STATE_CONNECTEDTb4b4b4) Tb4b4b4{ Tff7b72if Tb4b4b4(Tff7b72!Te6edf3fifo_isfullTb4b4b4(Tff7b72&Te6edf3serialFIFOTb4b4b4)Tb4b4b4) Tb4b4b4{ Te6edf3fifo_pushTb4b4b4(Tff7b72&Te6edf3serialFIFOTb4b4b4, Te6edf3SerialBTTb4b4b4.Td2a8ffreadTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4; Tb4b4b4} Tb4b4b4}
Tff7b72#Tff7b72if HAS_WIFI
Tff7b72else Tff7b72if Tb4b4b4(Te6edf3wifi_host_is_connectedTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{ Tff7b72if Tb4b4b4(Tff7b72!Te6edf3fifo_isfullTb4b4b4(Tff7b72&Te6edf3serialFIFOTb4b4b4)Tb4b4b4) Tb4b4b4{ Te6edf3fifo_pushTb4b4b4(Tff7b72&Te6edf3serialFIFOTb4b4b4, Te6edf3wifi_remote_readTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4; Tb4b4b4} Tb4b4b4}
Tff7b72#Tff7b72endif
Tff7b72else Tb4b4b4{ Tff7b72if Tb4b4b4(Tff7b72!Te6edf3fifo_isfullTb4b4b4(Tff7b72&Te6edf3serialFIFOTb4b4b4)Tb4b4b4) Tb4b4b4{ Te6edf3fifo_pushTb4b4b4(Tff7b72&Te6edf3serialFIFOTb4b4b4, Td2a8ffSerialTb4b4b4.Td2a8ffreadTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4; Tb4b4b4} Tb4b4b4}
Tff7b72#Tff7b72else
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3fifo_isfullTb4b4b4(Tff7b72&Te6edf3serialFIFOTb4b4b4)Tb4b4b4) Tb4b4b4{ Te6edf3fifo_pushTb4b4b4(Tff7b72&Te6edf3serialFIFOTb4b4b4, Td2a8ffSerialTb4b4b4.Td2a8ffreadTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4}
Tff7b72#Tff7b72endif

Te6edf3serial_buffering Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Tb4b4b4}

Tff7b72void Te6edf3serial_interrupt_initTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if MCU_VARIANT == MCU_1284P
Te6edf3TCCR3A Tff7b72= T79c0ff0Tb4b4b4;
Te6edf3TCCR3B Tff7b72= Te6edf3_BVTb4b4b4(Te6edf3CS10Tb4b4b4) Tff7b72|
Te6edf3_BVTb4b4b4(Te6edf3WGM33Tb4b4b4)Tff7b72|
Te6edf3_BVTb4b4b4(Te6edf3WGM32Tb4b4b4)Tb4b4b4;

T8b949e// Buffer incoming frames every 1ms
Te6edf3ICR3 Tff7b72= T79c0ff16000Tb4b4b4;
Te6edf3TIMSK3 Tff7b72= Te6edf3_BVTb4b4b4(Te6edf3ICIE3Tb4b4b4)Tb4b4b4;

Tff7b72#Tff7b72elif MCU_VARIANT == MCU_2560
T8b949e// TODO: This should probably be updated for
T8b949e// atmega2560 support. Might be source of
T8b949e// reported issues from snh.
Te6edf3TCCR3A Tff7b72= T79c0ff0Tb4b4b4;
Te6edf3TCCR3B Tff7b72= Te6edf3_BVTb4b4b4(Te6edf3CS10Tb4b4b4) Tff7b72|
Te6edf3_BVTb4b4b4(Te6edf3WGM33Tb4b4b4)Tff7b72|
Te6edf3_BVTb4b4b4(Te6edf3WGM32Tb4b4b4)Tb4b4b4;

T8b949e// Buffer incoming frames every 1ms
Te6edf3ICR3 Tff7b72= T79c0ff16000Tb4b4b4;
Te6edf3TIMSK3 Tff7b72= Te6edf3_BVTb4b4b4(Te6edf3ICIE3Tb4b4b4)Tb4b4b4;

Tff7b72#Tff7b72elif MCU_VARIANT == MCU_ESP32
T8b949e// No interrupt-based polling on ESP32
Tff7b72#Tff7b72endif

Tb4b4b4}

Tff7b72#Tff7b72if MCU_VARIANT == MCU_1284P || MCU_VARIANT == MCU_2560
Te6edf3ISRTb4b4b4(Te6edf3TIMER3_CAPT_vectTb4b4b4) Tb4b4b4{ Te6edf3buffer_serialTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72#Tff7b72endif

Served by rngit 1.5.4 - Generated in 0.26s